Seems that it's working!

This commit is contained in:
eddyem 2019-10-28 14:43:18 +03:00
parent d348acd7f9
commit 3263d6de4f
11 changed files with 477 additions and 177 deletions

View File

@ -24,6 +24,7 @@
// amount of encoder's counts when stop = rawspeed^2/STOPPING_COEFF // amount of encoder's counts when stop = rawspeed^2/STOPPING_COEFF
#define STOPPING_COEFF (117500L) #define STOPPING_COEFF (117500L)
//#define STOPPING_COEFF (1175000L)
// direction of motor rotation positive to encoder (1 - negative) // direction of motor rotation positive to encoder (1 - negative)
#define MOTOR_REVERSE (0) #define MOTOR_REVERSE (0)
@ -48,26 +49,26 @@
// moving timeout (*0.01s) // moving timeout (*0.01s)
#define MOVING_TIMEOUT 5000 #define MOVING_TIMEOUT 5000
// constants for focus conversion: foc_mm = (foc_raw - FOCRAW_0) / FOCSCALE_MM
#define FOCSCALE_MM 4096.
#define FOCRAW_0 40960.
#define FOC_RAW2MM(x) (((x)-FOCRAW_0)/FOCSCALE_MM)
#define FOC_MM2RAW(x) (FOCRAW_0+(x)*FOCSCALE_MM)
// raw position precision // raw position precision
#define RAWPOS_TOLERANCE 20 #define RAWPOS_TOLERANCE 10
// raw dF value for accurate focussing // raw dF value for accurate focussing
#define dF0 100 #define dF0 100
// minimal & maximal focus positions (should be >min+dF0 & <max-dF0) // minimal & maximal focus positions (should be >min+dF0 & <max-dF0)
#define FOCMIN 200
#define FOCMAX 320000
// focus raw positions @ endswitches (< or >)
#define FOCPOS_CW_ESW 5000
#define FOCPOS_CCW_ESW 315000
// the same in mm
#define FOCMIN_MM 0.1 #define FOCMIN_MM 0.1
#define FOCMAX_MM 76.0 #define FOCMAX_MM 76.0
// -//- raw values
#define FOCMIN FOC_MM2RAW(FOCMIN_MM)
#define FOCMAX FOC_MM2RAW(FOCMAX_MM)
// permitted distance to end-switch // permitted distance to end-switch
#define ESW_DIST_ALLOW 1.0 #define ESW_DIST_ALLOW 1.0
// focus raw positions @ endswitches (< or >)
// constants for focus conversion: foc_mm = (foc_raw - FOCRAW_MM0) / FOCSCALE_MM #define FOCPOS_CW_ESW FOC_MM2RAW((FOCMAX_MM - ESW_DIST_ALLOW))
#define FOCSCALE_MM 4096. #define FOCPOS_CCW_ESW FOC_MM2RAW((FOCMIN_MM + ESW_DIST_ALLOW))
#define FOCRAW_MM0 0
#define FOC_RAW2MM(x) ((x-FOCRAW_MM0)/FOCSCALE_MM)
#define FOC_MM2RAW(x) (FOCRAW_MM0+x*FOCSCALE_MM)
#endif // HW_DEPENDENT__ #endif // HW_DEPENDENT__

View File

@ -31,24 +31,31 @@ extern int verbose(const char *fmt, ...);
// CAN bus IDs: for motor's functions (PI ID [F=4] == PO ID[F=3] + 1) and parameters // CAN bus IDs: for motor's functions (PI ID [F=4] == PO ID[F=3] + 1) and parameters
static unsigned long motor_id = 0, motor_p_id = 0;//, bcast_id = 1; static unsigned long motor_id = 0, motor_p_id = 0;//, bcast_id = 1;
// current motor position // current motor position (RAW)
static unsigned long curposition = 0; static unsigned long curposition = 0;
// encoder's node number // encoder's node number
static int encnodenum = 0; static int encnodenum = 0;
// system status // system status
static sysstatus curstatus = STAT_OK; static sysstatus curstatus = STAT_OK;
// current raw motor speed (without MOTOR_REVERSE)
int16_t targspd = 0;
static canstatus can_write_par(uint8_t subidx, uint16_t idx, uint32_t *parval); static canstatus can_write_par(uint8_t subidx, uint16_t idx, uint32_t *parval);
static canstatus can_read_par(uint8_t subidx, uint16_t idx, uint32_t *parval); static canstatus can_read_par(uint8_t subidx, uint16_t idx, uint32_t *parval);
static int move(unsigned long targposition, int16_t rawspeed); static int move(unsigned long targposition, int16_t rawspeed);
static int waitTillStop();
// check if end-switches are in default state
// return 0 if all OK // return 0 if all OK
static int chk_eswstates(){ static int chk_eswstates(){
FNAME();
uint32_t cw, ccw; uint32_t cw, ccw;
if(CAN_NOERR != can_read_par(PAR_DI_SUBIDX, PAR_CW_IDX, &cw)) goto verybad; if(CAN_NOERR != can_read_par(PAR_DI_SUBIDX, PAR_CW_IDX, &cw)) goto verybad;
if(CAN_NOERR != can_read_par(PAR_DI_SUBIDX, PAR_CCW_IDX, &ccw)) goto verybad; if(CAN_NOERR != can_read_par(PAR_DI_SUBIDX, PAR_CCW_IDX, &ccw)) goto verybad;
uint32_t parval = DI_ENSTOP; uint32_t parval = DI_ENSTOP;
if(cw != DI_ENSTOP || ccw != DI_ENSTOP){ // activate enable/stop if(cw != DI_ENSTOP || ccw != DI_ENSTOP){ // activate enable/stop
WARNX("\n\nThe end-switches state wasn't default!"); WARNX("\nThe end-switches state wasn't default!");
if(waitTillStop()) return 1; // we can change motor parameters only in stopped state
if(CAN_NOERR != can_write_par(PAR_DI_SUBIDX, PAR_CW_IDX, &parval)) goto verybad; if(CAN_NOERR != can_write_par(PAR_DI_SUBIDX, PAR_CW_IDX, &parval)) goto verybad;
if(CAN_NOERR != can_write_par(PAR_DI_SUBIDX, PAR_CCW_IDX, &parval)) goto verybad; if(CAN_NOERR != can_write_par(PAR_DI_SUBIDX, PAR_CCW_IDX, &parval)) goto verybad;
} }
@ -59,6 +66,50 @@ verybad:
return 1; return 1;
} }
/**
* @brief chkMove - check whether moving available
* @param spd - speed (used only its sign) before MOTOR_REVERSE!
* @return 0 if all OK
*/
static int chkMove(int spd){
//FNAME();
if(curstatus == STAT_DAMAGE){
WARNX("Try to move in damaged state");
return 1;
}
eswstate e;
if(CAN_NOERR != get_endswitches(&e)){
curstatus = STAT_ERROR;
return 1;
}
if(e == ESW_INACTIVE){
if(getPos(NULL)) return 1;
if(curposition <= FOCMIN && spd < 0){
WARNX("Try to move to the left of minimal position");
return 1;
}
if(curposition >= FOCMAX && spd > 0){
WARNX("Try to move to the right of maximal position");
return 1;
}
return 0;
}
if(e == ESW_BOTH_ACTIVE){
curstatus = STAT_DAMAGE;
return 1;
}
if(e == ESW_CCW_ACTIVE && spd < 0){
curstatus = STAT_ESW;
WARNX("Try to move over the CCW end-switch");
return 1;
}else if(e == ESW_CW_ACTIVE && spd > 0){
curstatus = STAT_ESW;
WARNX("Try to move over the CW end-switch");
return 1;
}
return 0;
}
/** /**
* @brief init_encoder - encoder's interface initialisation * @brief init_encoder - encoder's interface initialisation
* @param encnode - encoder's node number * @param encnode - encoder's node number
@ -135,32 +186,41 @@ int init_encoder(int encnode, int reset){
* @return 0 if all OK * @return 0 if all OK
*/ */
int go_out_from_ESW(){ int go_out_from_ESW(){
uint32_t cw, ccw, parval; FNAME();
// check esw roles uint32_t parval;
if(CAN_NOERR != can_read_par(PAR_DI_SUBIDX, PAR_CW_IDX, &cw)) goto bad; if(chk_eswstates()) return 1;
if(CAN_NOERR != can_read_par(PAR_DI_SUBIDX, PAR_CCW_IDX, &ccw)) goto bad;
parval = DI_ENSTOP;
if(cw != DI_ENSTOP || ccw != DI_ENSTOP){ // activate enable/stop
if(CAN_NOERR != can_write_par(PAR_DI_SUBIDX, PAR_CW_IDX, &parval)) goto bad;
if(CAN_NOERR != can_write_par(PAR_DI_SUBIDX, PAR_CCW_IDX, &parval)) goto bad;
}
// check esw // check esw
eswstate e; eswstate e;
getPos(NULL);
if(CAN_NOERR != get_endswitches(&e)){ if(CAN_NOERR != get_endswitches(&e)){
WARNX("Can't read end-switches state");
return 1; return 1;
} }
if(e == ESW_BOTH_ACTIVE){ // error situation! if(e == ESW_BOTH_ACTIVE){ // error situation!
WARNX("Error: both end-switches are active!"); WARNX("Error: both end-switches are active!");
curstatus = STAT_BOTHESW; curstatus = STAT_DAMAGE;
return 1; return 1;
} }
if(e == ESW_INACTIVE){ if(e == ESW_INACTIVE){
DBG("Esw inactive"); DBG("Esw inactive");
int r = 0;
if(curposition < FOCMIN) r = move(FOCMIN, MAXSPEED);
else if(curposition > FOCMAX) r = move(FOCMAX, -MAXSPEED);
curstatus = STAT_OK; curstatus = STAT_OK;
return 0; return r;
} }
curstatus = STAT_GOFROMESW; curstatus = STAT_GOFROMESW;
// check that current position is in available zone
if(e == ESW_CW_ACTIVE && curposition < FOCPOS_CW_ESW){
// WTF? CW end-switch activated in forbidden zone!
WARNX("CW end-switch in forbidden zone (to the left of normal position)!");
curstatus = STAT_DAMAGE;
return 1;
}else if(e == ESW_CCW_ACTIVE && curposition > FOCPOS_CW_ESW){
// CCW end-switch activated in forbidden zone!
WARNX("CCW end-switch in forbidden zone (too far)!");
curstatus = STAT_DAMAGE;
return 1;
}
// try to move from esw // try to move from esw
parval = DI_NOFUNC; parval = DI_NOFUNC;
uint16_t idx = (e == ESW_CW_ACTIVE) ? PAR_CW_IDX : PAR_CCW_IDX; uint16_t idx = (e == ESW_CW_ACTIVE) ? PAR_CW_IDX : PAR_CCW_IDX;
@ -170,23 +230,17 @@ int go_out_from_ESW(){
getPos(NULL); getPos(NULL);
DBG("try %d, pos: %lu, E=%d", i, curposition, e); DBG("try %d, pos: %lu, E=%d", i, curposition, e);
unsigned long targ = (e == ESW_CW_ACTIVE) ? curposition - (double)FOCSCALE_MM*0.2 : curposition + (double)FOCSCALE_MM*0.2; unsigned long targ = (e == ESW_CW_ACTIVE) ? curposition - (double)FOCSCALE_MM*0.2 : curposition + (double)FOCSCALE_MM*0.2;
if(targ > FOCMAX) targ = FOCMAX;
else if(targ < FOCMIN) targ = FOCMIN;
if(move(targ, speed)) continue; if(move(targ, speed)) continue;
get_endswitches(&e); get_endswitches(&e);
if(e == ESW_INACTIVE) break; if(e == ESW_INACTIVE) break;
} }
// return esw state if(chk_eswstates()) return 1;
parval = DI_ENSTOP;
if(CAN_NOERR != can_write_par(PAR_DI_SUBIDX, PAR_CW_IDX, &parval)) goto bad;
if(CAN_NOERR != can_write_par(PAR_DI_SUBIDX, PAR_CCW_IDX, &parval)) goto bad;
if(e != ESW_INACTIVE){
WARNX("Can't move out of end-switch");
curstatus = STAT_ERROR;
return 1;
}
curstatus = STAT_OK; curstatus = STAT_OK;
return 0; return 0;
bad: bad:
WARNX("Can't get/set esw parameters"); WARNX("Can't move out from end-switch");
curstatus = STAT_ERROR; curstatus = STAT_ERROR;
return 1; return 1;
} }
@ -216,28 +270,39 @@ int init_motor_ids(int addr){
* @return 0 if all OK * @return 0 if all OK
*/ */
int getPos(double *pos){ int getPos(double *pos){
//FNAME();
int r = !(getLong(encnodenum, DS406_POSITION_VAL, 0, &curposition)); int r = !(getLong(encnodenum, DS406_POSITION_VAL, 0, &curposition));
if(pos) *pos = FOC_RAW2MM(curposition); if(pos) *pos = FOC_RAW2MM(curposition);
eswstate e; eswstate e;
if(CAN_NOERR != get_endswitches(&e)){ if(CAN_NOERR != get_endswitches(&e)){
WARNX("Can't read end-switches state");
curstatus = STAT_ERROR; curstatus = STAT_ERROR;
}else switch(e){ }else switch(e){
case ESW_BOTH_ACTIVE: case ESW_BOTH_ACTIVE:
curstatus = STAT_BOTHESW; curstatus = STAT_DAMAGE;
break; break;
case ESW_CCW_ACTIVE: case ESW_CCW_ACTIVE:
if(curposition > FOCPOS_CCW_ESW) curstatus = STAT_BADESW; if(curposition > FOCPOS_CCW_ESW) curstatus = STAT_DAMAGE;
else curstatus = STAT_ESW; else curstatus = STAT_ESW;
break; break;
case ESW_CW_ACTIVE: case ESW_CW_ACTIVE:
if(curposition < FOCPOS_CW_ESW) curstatus = STAT_BADESW; if(curposition < FOCPOS_CW_ESW) curstatus = STAT_DAMAGE;
else curstatus = STAT_ESW; else curstatus = STAT_ESW;
break; break;
case ESW_INACTIVE: case ESW_INACTIVE:
default: default:
curstatus = STAT_OK; curstatus = STAT_OK;
} }
if(targspd){
if(curposition <= FOCMIN && targspd < 0){ // bad value
WARNX("Forbidden position < FOCMIN!");
stop();
curstatus = STAT_FORBIDDEN;
}else if(curposition >= FOCMAX && targspd > 0){
WARNX("Forbidden position > FOCMAX!");
stop();
curstatus = STAT_FORBIDDEN;
}
}
return r; return r;
} }
@ -262,8 +327,8 @@ void returnPreOper(){
} }
/** /**
* @brief fix_targspeed - fix raw speed value if it is greater MAXSPEED or less than MINSPEED * @brief fix_targspeed - fix speed value if it is greater MAXSPEED or less than MINSPEED
* @param targspd (io) - raw target speed * @param targspd (io) - target speed in rev/min
*/ */
static void fix_targspeed(int16_t *targspd){ static void fix_targspeed(int16_t *targspd){
if(!targspd) return; if(!targspd) return;
@ -302,7 +367,7 @@ static canstatus can_send_chk(unsigned char *buf, unsigned char *obuf){
can_dsleep(0.01); can_dsleep(0.01);
} }
if(I == 50){ if(I == 50){
WARNX("Error getting answer"); WARNX("can_send_chk(): error getting answer");
return CAN_NOANSWER; return CAN_NOANSWER;
} }
if(obuf) memcpy(obuf, rdata, l); if(obuf) memcpy(obuf, rdata, l);
@ -336,25 +401,26 @@ static canstatus can_send_param(unsigned char *buf, unsigned char *obuf){
int I, rxpnt, idr, dlen; int I, rxpnt, idr, dlen;
double rxtime; double rxtime;
unsigned char rdata[8]; unsigned char rdata[8];
can_clean_recv(&rxpnt, &rxtime); /*
if(can_send_frame(motor_p_id, l, buf) <= 0){
WARNX("Error sending CAN frame (len %d)", l);
return CAN_CANTSEND;
}
/*
green("Sent param: "); green("Sent param: ");
for(int i=0; i<l; ++i) printf("0x%02x ", buf[i]); for(int i=0; i<l; ++i) printf("0x%02x ", buf[i]);
printf("\n"); printf("\n");
*/ */
if(can_send_frame(motor_p_id, l, buf) <= 0){
WARNX("Error sending CAN frame (len %d)", l);
return CAN_CANTSEND;
}
can_clean_recv(&rxpnt, &rxtime);
for(I = 0; I < 50; ++I){ for(I = 0; I < 50; ++I){
if(can_recv_frame(&rxpnt, &rxtime, &idr, &dlen, rdata) && (idr&0x1fffffff) == motor_p_id+1) break; if(can_recv_frame(&rxpnt, &rxtime, &idr, &dlen, rdata) && (idr&0x1fffffff) == motor_p_id+1) break;
//DBG("Got frame from ID 0x%x", idr&0x1fffffff);
can_dsleep(0.01); can_dsleep(0.01);
} }
if(I == 50){ if(I == 50){
WARNX("Error getting answer"); WARNX("can_send_param(): error getting answer");
return CAN_NOANSWER; return CAN_NOANSWER;
} }
/* /*
green("Received param: "); green("Received param: ");
for(int i=0; i<dlen; ++i) printf("0x%02x ", rdata[i]); for(int i=0; i<dlen; ++i) printf("0x%02x ", rdata[i]);
printf("\n"); printf("\n");
@ -402,15 +468,15 @@ static canstatus can_write_par(uint8_t subidx, uint16_t idx, uint32_t *parval){
buf[3] = idx & 0xff; buf[3] = idx & 0xff;
if(parval){ if(parval){
uint32_t par = *parval; uint32_t par = *parval;
obuf[4] = (par >> 24) & 0xff; DBG("parameter: %d", par);
obuf[5] = (par >> 16) & 0xff; buf[4] = (par >> 24) & 0xff;
obuf[6] = (par >> 8) & 0xff; buf[5] = (par >> 16) & 0xff;
obuf[7] = par & 0xff; buf[6] = (par >> 8) & 0xff;
buf[7] = par & 0xff;
} }
return can_send_param(buf, obuf); return can_send_param(buf, obuf);
} }
/** /**
* @brief get_motor_speed * @brief get_motor_speed
* @param motstatus (o) - status (if !NULL) * @param motstatus (o) - status (if !NULL)
@ -427,14 +493,6 @@ canstatus get_motor_speed(double *spd){
return s; return s;
} }
*spd = (double)speed.i / 1000.; *spd = (double)speed.i / 1000.;
/*
union{
int16_t i16;
uint8_t c8[2];
} mspd;
mspd.c8[0] = rdata[3];
mspd.c8[1] = rdata[2];
*/
return CAN_NOERR; return CAN_NOERR;
} }
@ -444,8 +502,13 @@ canstatus get_motor_speed(double *spd){
* @return * @return
*/ */
canstatus get_endswitches(eswstate *Esw){ canstatus get_endswitches(eswstate *Esw){
//FNAME();
uint32_t val = 0; uint32_t val = 0;
canstatus s = can_read_par(PAR_DI_SUBIDX, PAR_DIST_IDX, &val); canstatus s = can_read_par(PAR_DI_SUBIDX, PAR_DIST_IDX, &val);
if(s != CAN_NOERR){
WARNX("Can't read end-switches state");
return s;
}
if(Esw){ if(Esw){
int v = 0; int v = 0;
if(!(val & ESW_CW)){ // + pressed if(!(val & ESW_CW)){ // + pressed
@ -464,27 +527,68 @@ canstatus get_endswitches(eswstate *Esw){
* @return 0 if all OK * @return 0 if all OK
*/ */
int stop(){ int stop(){
FNAME();
unsigned char buf[6] = {0, CW_STOP,0,}; unsigned char buf[6] = {0, CW_STOP,0,};
if(can_send_chk(buf, NULL)){ if(can_send_chk(buf, NULL)){
WARNX("Can't stop motor!"); WARNX("Can't stop motor!");
return 1; return 1;
} }
targspd = 0;
return 0;
}
/**
* @brief waitTillStop - wait for full stop
*/
static int waitTillStop(){
long oldposition = -1;
double spd;
int r = 0;
if(CAN_NOERR == get_motor_speed(&spd)){
DBG("speed: %g, targspd: %d", spd, targspd);
if(fabs(spd) > DBL_EPSILON || targspd) r = stop();
}else r = stop();
if(r) r = stop();
if(!r){
do{ // wait till stop
can_dsleep(0.1);
if(CAN_NOERR == get_motor_speed(&spd)){
if(fabs(spd) > DBL_EPSILON){
//DBG("Still moving, spd=%g", spd);
//stop();
continue; // wait for zero-speed
}else{
DBG("OK, stopped, spd=%g", spd);
}
}else{DBG("can't get motor speed");};
oldposition = curposition;
// now wait for full moving stop
getLong(encnodenum, DS406_POSITION_VAL, 0, &curposition);
//DBG("curpos: %lu, oldpos: %ld", curposition, oldposition);
}while((long)curposition != oldposition);
}else{
curstatus = STAT_ERROR;
return 1;
}
return 0; return 0;
} }
/** /**
* @brief movewconstspeed - move with constant speed * @brief movewconstspeed - move with constant speed
* @param rawspd - given speed * @param spd - given speed (rev/min)
* @return 0 if all OK * @return 0 if all OK
*/ */
int movewconstspeed(int spd){ int movewconstspeed(int16_t spd){
if(chk_eswstates()) return 1; if(chkMove(spd)) return 1;
int16_t targspd = RAWSPEED(spd); fix_targspeed(&spd);
targspd = RAWSPEED(spd);
unsigned char buf[8] = {0,}; unsigned char buf[8] = {0,};
buf[1] = CW_ENABLE; buf[1] = CW_ENABLE;
if(MOTOR_REVERSE) spd = -spd; int16_t s = targspd;
buf[2] = (targspd >> 8) & 0xff; if(MOTOR_REVERSE) s = -s;
buf[3] = targspd & 0xff; buf[2] = (s >> 8) & 0xff;
buf[3] = s & 0xff;
DBG("\tBUF: %d, %d, %d, %d", buf[0], buf[1], buf[2], buf[3]);
if(can_send_chk(buf, NULL)){ if(can_send_chk(buf, NULL)){
WARNX("Can't move motor!"); WARNX("Can't move motor!");
return 1; return 1;
@ -495,27 +599,32 @@ int movewconstspeed(int spd){
/** /**
* @brief move - move focuser from current position to approximately `targposition` with speed `rawspeed` * @brief move - move focuser from current position to approximately `targposition` with speed `rawspeed`
* @param targposition - target position in raw value * @param targposition - target position in raw value
* @param rawspeed - speed in raw value * @param rawspeed - raw speed value
* @return 0 if all OK * @return 0 if all OK
*/ */
static int move(unsigned long targposition, int16_t rawspeed){ static int move(unsigned long targposition, int16_t rawspeed){
//FNAME();
if(abs(targposition - curposition) < RAWPOS_TOLERANCE){ if(abs(targposition - curposition) < RAWPOS_TOLERANCE){
verbose("Already at position\n"); verbose("Already at position\n");
DBG("Already at position");
return 0; return 0;
} }
if(chk_eswstates()) return 1; if(chkMove(rawspeed)) return 1;
unsigned char buf[6] = {0,}; unsigned char buf[6] = {0,};
DBG("Start moving with speed %d", rawspeed); DBG("Start moving with speed %d, target position: %lu", rawspeed, targposition);
buf[1] = CW_ENABLE; buf[1] = CW_ENABLE;
targspd = rawspeed;
if(MOTOR_REVERSE) rawspeed = -rawspeed; if(MOTOR_REVERSE) rawspeed = -rawspeed;
buf[2] = (rawspeed >> 8) & 0xff; buf[2] = (rawspeed >> 8) & 0xff;
buf[3] = rawspeed & 0xff; buf[3] = rawspeed & 0xff;
DBG("\tBUF: %d, %d, %d, %d", buf[0], buf[1], buf[2], buf[3]); DBG("\tBUF: %d, %d, %d, %d", buf[0], buf[1], buf[2], buf[3]);
//unsigned char obuf[8];
if(can_send_chk(buf, NULL)){ if(can_send_chk(buf, NULL)){
WARNX("Can't move motor!"); WARNX("Can't move motor!");
stop(); stop();
return 1; return 1;
} }
//DBG("\tOBUF: %d, %d, %d, %d, %d, %d", obuf[0], obuf[1], obuf[2], obuf[3], obuf[4], obuf[5]);
#ifdef EBUG #ifdef EBUG
double t0 = can_dtime(); double t0 = can_dtime();
#endif #endif
@ -523,9 +632,9 @@ static int move(unsigned long targposition, int16_t rawspeed){
long corrvalue = (long)rawspeed*(long)rawspeed / STOPPING_COEFF; // correction due to stopping ramp long corrvalue = (long)rawspeed*(long)rawspeed / STOPPING_COEFF; // correction due to stopping ramp
DBG("start-> curpos: %ld, difference: %ld, corrval: %ld, tm=%g", DBG("start-> curpos: %ld, difference: %ld, corrval: %ld, tm=%g",
curposition, olddiffr, corrvalue, can_dtime()-t0); curposition, olddiffr, corrvalue, can_dtime()-t0);
int i, zerctr = 0; int i, zerctr = 0, errctr = 0;
for(i = 0; i < MOVING_TIMEOUT; ++i){ for(i = 0; i < MOVING_TIMEOUT; ++i){
can_dsleep(0.01); can_dsleep(0.001);
//uint16_t motstat; //uint16_t motstat;
double speed; double speed;
if(emerg_stop){ // emergency stop activated if(emerg_stop){ // emergency stop activated
@ -541,42 +650,11 @@ static int move(unsigned long targposition, int16_t rawspeed){
return 1; return 1;
} }
getPos(NULL); getPos(NULL);
if(curstatus != STAT_OK){ if(chkMove(targspd)){
WARNX("Something bad with end-switches"); WARNX("Can't move further!");
stop(); stop();
return 1; return 1;
} }
/* eswstate esw;
if(get_endswitches(&esw) != CAN_NOERR){
WARNX("Can't get endswitches state, stopping");
stop();
curstatus = STAT_ERROR;
return 1;
}
if(esw != ESW_INACTIVE){ // OOps, something wrong
if(esw == ESW_BOTH_ACTIVE){ // error!
WARNX("Check end-switches, both active!");
curstatus = STAT_BOTHESW;
stop();
return 1;
}
//TODO: check wrong end-switches!
if(rawspeed > 0){ // moving CW, don't care for CCW esw state
if(esw == ESW_CW_ACTIVE){
WARNX("CW mowing: end-switch!");
curstatus = STAT_ESW;
stop();
return 1;
}
}else{ // movig CCW
if(esw == ESW_CCW_ACTIVE){
WARNX("CCW mowing: end-switch!");
curstatus = STAT_ESW;
stop();
return 1;
}
}
}*/
if(fabs(speed) < 0.1){ // || (motstat & (SW_B_UNBLOCK|SW_B_READY|SW_B_POUNBLOCK)) != (SW_B_UNBLOCK|SW_B_READY|SW_B_POUNBLOCK)){ if(fabs(speed) < 0.1){ // || (motstat & (SW_B_UNBLOCK|SW_B_READY|SW_B_POUNBLOCK)) != (SW_B_UNBLOCK|SW_B_READY|SW_B_POUNBLOCK)){
if(++zerctr == 10){ if(++zerctr == 10){
WARNX("Motor stopped while moving!"); WARNX("Motor stopped while moving!");
@ -587,12 +665,17 @@ static int move(unsigned long targposition, int16_t rawspeed){
}else zerctr = 0; }else zerctr = 0;
if(!getLong(encnodenum, DS406_POSITION_VAL, 0, &curposition)) continue; if(!getLong(encnodenum, DS406_POSITION_VAL, 0, &curposition)) continue;
long diffr = targposition - curposition; long diffr = targposition - curposition;
//DBG("Speed: %g, curpos: %ld, diff: %ld", speed, curposition, diffr); DBG("Speed: %g, curpos: %ld, diff: %ld", speed, curposition, diffr);
if(abs(diffr) < corrvalue || abs(diffr) - RAWPOS_TOLERANCE > abs(olddiffr)){ if(abs(diffr) < corrvalue || abs(diffr) < RAWPOS_TOLERANCE){
DBG("OK! almost reach: olddif=%ld, diff=%ld, corrval=%ld, tm=%g", olddiffr, diffr, corrvalue, can_dtime()-t0); DBG("OK! almost reach: olddif=%ld, diff=%ld, corrval=%ld, tm=%g", olddiffr, diffr, corrvalue, can_dtime()-t0);
olddiffr = diffr; olddiffr = diffr;
break; break;
} }
if(abs(diffr) > abs(olddiffr)){
++errctr;
DBG("errctr: %d", errctr);
if(errctr > 50) break;
}
olddiffr = diffr; olddiffr = diffr;
} }
if(i == MOVING_TIMEOUT){ if(i == MOVING_TIMEOUT){
@ -602,20 +685,12 @@ static int move(unsigned long targposition, int16_t rawspeed){
return 1; return 1;
} }
DBG("end-> curpos: %ld, difference: %ld, tm=%g\n", curposition, targposition - curposition, can_dtime()-t0); DBG("end-> curpos: %ld, difference: %ld, tm=%g\n", curposition, targposition - curposition, can_dtime()-t0);
long oldposition; if(waitTillStop()) return 1;
int r = stop();
if(r) r = stop();
if(!r) do{ // wait till stop
oldposition = curposition;
can_dsleep(0.1);
getLong(encnodenum, DS406_POSITION_VAL, 0, &curposition);
//DBG("wait-> curpos: %ld, difference: %ld, tm=%g\n", curposition, targposition - curposition, can_dtime()-t0);
}while((long)curposition != oldposition);
if(abs(targposition - curposition) > RAWPOS_TOLERANCE) if(abs(targposition - curposition) > RAWPOS_TOLERANCE)
verbose("Current (%ld) position is too far from target (%ld)\n", curposition, targposition); verbose("Current (%ld) position is too far from target (%ld)\n", curposition, targposition);
DBG("stop-> curpos: %ld, difference: %ld, tm=%g\n", curposition, targposition - curposition, can_dtime()-t0); DBG("stop-> curpos: %ld, difference: %ld, tm=%g\n", curposition, targposition - curposition, can_dtime()-t0);
curstatus = STAT_OK; curstatus = STAT_OK;
return r; return 0;
} }
/** /**
@ -624,6 +699,7 @@ static int move(unsigned long targposition, int16_t rawspeed){
* @return 0 if all OK * @return 0 if all OK
*/ */
int move2pos(double target){ int move2pos(double target){
FNAME();
double cur; double cur;
if(getPos(&cur)){ if(getPos(&cur)){
WARNX("Can't get current position!"); WARNX("Can't get current position!");
@ -639,12 +715,18 @@ int move2pos(double target){
verbose("Already at position\n"); verbose("Already at position\n");
return 0; return 0;
} }
long targ0pos = (long)targposition + (long)dF0; long spd, targ0pos = (long)targposition + (long)dF0, absdiff = abs(targ0pos - (long)curposition),
long spd = (targ0pos - (long)curposition) / 2L; sign = (targ0pos > (long)curposition) ? 1 : -1;
DBG("absdiff: %ld", absdiff);
//long spd = (targ0pos - (long)curposition) / 2L;
if(absdiff > 1000) spd = sign*MAXSPEED;
else if(absdiff > 500) spd = sign*MAXSPEED / 2;
else if(absdiff > 200) spd = sign*MAXSPEED / 4;
else spd = sign*MINSPEED;
int16_t targspd = (int16_t) spd; int16_t targspd = (int16_t) spd;
if(spd > INT16_MAX) targspd = INT16_MAX; /* if(spd > INT16_MAX) targspd = INT16_MAX;
else if(spd < INT16_MIN) targspd = INT16_MIN; else if(spd < INT16_MIN) targspd = INT16_MIN;
fix_targspeed(&targspd); fix_targspeed(&targspd);*/
// check moving direction: thin focus correction always should run to negative! // check moving direction: thin focus correction always should run to negative!
if(targposition < curposition){ // we are from the right if(targposition < curposition){ // we are from the right
if(targspd < -MINSPEED*3/2){ // omit rough moving to focus value if there's too little distance towards target if(targspd < -MINSPEED*3/2){ // omit rough moving to focus value if there's too little distance towards target
@ -657,6 +739,7 @@ int move2pos(double target){
}else{ // we are from the left - move to the point @ right side of target }else{ // we are from the left - move to the point @ right side of target
DBG("1) ROUGH move to the RIGHT: curpos=%ld, difference=%ld\n", curposition, targ0pos - (long)curposition); DBG("1) ROUGH move to the RIGHT: curpos=%ld, difference=%ld\n", curposition, targ0pos - (long)curposition);
if(move(targ0pos, RAWSPEED(targspd))){ if(move(targ0pos, RAWSPEED(targspd))){
DBG("Error in move?");
return 1; return 1;
} }
} }
@ -667,6 +750,7 @@ int move2pos(double target){
} }
if(abs(targposition - curposition) < RAWPOS_TOLERANCE){ if(abs(targposition - curposition) < RAWPOS_TOLERANCE){
verbose("Catch the position @ rough movint\n"); verbose("Catch the position @ rough movint\n");
DBG("Catch the position @ rough movint");
return 0; return 0;
} }
if(curposition < targposition){ if(curposition < targposition){
@ -674,6 +758,10 @@ int move2pos(double target){
return 1; return 1;
} }
DBG("2) curpos: %ld, difference: %ld\n", curposition, (long)targposition - (long)curposition); DBG("2) curpos: %ld, difference: %ld\n", curposition, (long)targposition - (long)curposition);
//sleep(3);
/*DBG("NOW MOVE");
move(targposition, -800);
DBG("NOW MOVE MORE");*/
// now make an accurate moving // now make an accurate moving
if(move(targposition, -(RAWSPEED(MINSPEED)))){ if(move(targposition, -(RAWSPEED(MINSPEED)))){
WARNX("Can't catch focus precisely!"); WARNX("Can't catch focus precisely!");
@ -687,11 +775,12 @@ int move2pos(double target){
verbose("Stopped over the accuracy range\n"); verbose("Stopped over the accuracy range\n");
return 1; return 1;
} }
return stop(); return 0;
} }
// return 0 if all OK // return 0 if all OK
static int get_pos_speed(unsigned long *pos, double *speed){ int get_pos_speed(unsigned long *pos, double *speed){
FNAME();
int ret = 0; int ret = 0;
if(pos){ if(pos){
if(!getLong(encnodenum, DS406_POSITION_VAL, 0, pos)) ret = 1; if(!getLong(encnodenum, DS406_POSITION_VAL, 0, pos)) ret = 1;

View File

@ -43,10 +43,10 @@ typedef enum{
STAT_OK, // all OK STAT_OK, // all OK
// blocking statuses: // blocking statuses:
STAT_ESW, // end-switch active STAT_ESW, // end-switch active
STAT_BADESW, // wrong end-switch active
STAT_BOTHESW, // both end-switches active
STAT_GOFROMESW, // mowing from end-switch STAT_GOFROMESW, // mowing from end-switch
STAT_ERROR // uncoverable error STAT_ERROR, // error state
STAT_FORBIDDEN, // forbidden position
STAT_DAMAGE // the device in damaged state and can't work further
} sysstatus; } sysstatus;
int init_encoder(int encnode, int reset); int init_encoder(int encnode, int reset);
@ -59,8 +59,9 @@ canstatus get_motor_speed(double *spd);
canstatus get_endswitches(eswstate *Esw); canstatus get_endswitches(eswstate *Esw);
int move2pos(double target); int move2pos(double target);
int stop(); int stop();
int movewconstspeed(int spd); int movewconstspeed(int16_t spd);
int go_out_from_ESW(); int go_out_from_ESW();
sysstatus get_status(); sysstatus get_status();
int get_pos_speed(unsigned long *pos, double *speed);
#endif // CAN_ENCODER_H__ #endif // CAN_ENCODER_H__

135
Z1000_focus/checkfile.c Normal file
View File

@ -0,0 +1,135 @@
/*
* daemon.c - functions for running in background like a daemon
*
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <unistd.h> // getpid, unlink
#include <dirent.h> // opendir
#include "checkfile.h"
#include "usefull_macros.h"
/**
* @brief readPSname - read process name from /proc/PID/cmdline
* @param pid - PID of interesting process
* @return filename or NULL if not found
* don't use this function twice for different names without copying
* its returning by strdup, because `name` contains in static array
*/
char *readPSname(pid_t pid){
static char name[PATH_MAX];
char *pp = name, byte, path[PATH_MAX];
FILE *file;
int cntr = 0;
size_t sz;
snprintf(path, PATH_MAX, PROC_BASE "/%d/cmdline", pid);
file = fopen(path, "r");
if(!file) return NULL; // there's no such file
do{ // read basename
sz = fread(&byte, 1, 1, file);
if(sz != 1) break;
if(byte != '/') *pp++ = byte;
else{
pp = name;
cntr = 0;
}
}while(byte && cntr++ < PATH_MAX-1);
name[cntr] = 0;
fclose(file);
return name;
}
/**
* @brief iffound_default - default action when running process found
* @param pid - another process' pid
* Redefine this function for user action
*/
void WEAK iffound_default(pid_t pid){
/// \nïÂÎÁÒÕÖÅÎ ÏÄÎÏÉÍÅÎÎÙÊ ÐÒÏÃÅÓÓ (pid=%d), ×ÙÈÏÄ.\n
ERRX("\nFound running process (pid=%d), exit.\n", pid);
}
static char *pidfilename_ = NULL; // store the name of pidfile here
/**
* check wether there is a same running process
* exit if there is a running process or error
* Checking have 3 steps:
* 1) lock executable file
* 2) check pidfile (if you run a copy?)
* 3) check /proc for executables with the same name (no/wrong pidfile)
* @param pidfilename - name of pidfile or NULL if none
*/
void check4running(char *pidfilename){
DIR *dir;
FILE *pidfile;
struct dirent *de;
struct stat s_buf;
pid_t pid = 0, self;
char *name, *myname;
self = getpid(); // get self PID
if(!(dir = opendir(PROC_BASE))){ // open /proc directory
ERR(PROC_BASE);
}
if(!(name = readPSname(self))){ // error reading self name
ERR("Can't read self name");
}
myname = strdup(name);
if(pidfilename && stat(pidfilename, &s_buf) == 0){ // pidfile exists
pidfile = fopen(pidfilename, "r");
if(pidfile){
if(fscanf(pidfile, "%d", &pid) > 0){ // read PID of (possibly) running process
if((name = readPSname(pid)) && strncmp(name, myname, 255) == 0){
iffound_default(pid);
fclose(pidfile);
free(myname);
closedir(dir);
return;
}
}
fclose(pidfile);
}
}
// There is no pidfile or it consists a wrong record
while((de = readdir(dir))){ // scan /proc
if(!(pid = (pid_t)atoi(de->d_name)) || pid == self) // pass non-PID files and self
continue;
if((name = readPSname(pid)) && strncmp(name, myname, 255) == 0)
iffound_default(pid);
}
closedir(dir);
free(myname);
// OK, not found -> create pid-file if need
if(pidfilename){
pidfile = fopen(pidfilename, "w");
/// îÅ ÍÏÇÕ ÏÔËÒÙÔØ PID ÆÁÊÌ
if(!pidfile) ERR("Can't open PID file");
fprintf(pidfile, "%d\n", self); // write self PID to pidfile
fclose(pidfile);
pidfilename_ = strdup(pidfilename);
}
}
/**
* @brief unlink_pidfile - remove pidfile @ exit
*/
void unlink_pidfile(){
if(!pidfilename_) return;
unlink(pidfilename_);
FREE(pidfilename_);
}

39
Z1000_focus/checkfile.h Normal file
View File

@ -0,0 +1,39 @@
/*
* This file is part of the Zphocus project.
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef CHECKFILE_H__
#define CHECKFILE_H__
#ifndef PROC_BASE
#define PROC_BASE "/proc"
#endif
#ifndef WEAK
#define WEAK __attribute__ ((weak))
#endif
// default function to run if another process found
void WEAK iffound_default(pid_t pid);
// check that our process is exclusive
void check4running(char *pidfilename);
// read name of process by its PID
char *readPSname(pid_t pid);
void unlink_pidfile();
#endif // CHECKFILE_H__

View File

@ -33,13 +33,16 @@
int help; int help;
glob_pars G; glob_pars G;
#define DEFPIDNAME "/tmp/z1000focus.pid"
// DEFAULTS // DEFAULTS
// default global parameters // default global parameters
glob_pars const Gdefault = { glob_pars const Gdefault = {
.nodenum = 3, .nodenum = 3,
.motorID = 12, .motorID = 12,
.gotopos = NAN, .gotopos = NAN,
.port = DEFPORT .port = DEFPORT,
.pidfilename = DEFPIDNAME
}; };
/* /*
@ -53,7 +56,6 @@ myoption cmdlnopts[] = {
{"reset", NO_ARGS, NULL, 'r', arg_none, APTR(&G.reset), "reset encoder"}, {"reset", NO_ARGS, NULL, 'r', arg_none, APTR(&G.reset), "reset encoder"},
{"verbose", NO_ARGS, NULL, 'v', arg_int, APTR(&G.verbose), "show more info"}, {"verbose", NO_ARGS, NULL, 'v', arg_int, APTR(&G.verbose), "show more info"},
{"motorid", NEED_ARG, NULL, 'i', arg_int, APTR(&G.motorID), "motor controller address"}, {"motorid", NEED_ARG, NULL, 'i', arg_int, APTR(&G.motorID), "motor controller address"},
//{"bcastid", NEED_ARG, NULL, 'b', arg_int, APTR(&G.motorID), "motor controller broadcast address"},
{"gotopos", NEED_ARG, NULL, 'g', arg_double, APTR(&G.gotopos), "target focus position"}, {"gotopos", NEED_ARG, NULL, 'g', arg_double, APTR(&G.gotopos), "target focus position"},
{"targspeed",NEED_ARG, NULL, 't', arg_double, APTR(&G.targspeed), "move motor with constant speed (rev/min)"}, {"targspeed",NEED_ARG, NULL, 't', arg_double, APTR(&G.targspeed), "move motor with constant speed (rev/min)"},
{"stop", NO_ARGS, NULL, 's', arg_none, APTR(&G.stop), "stop motor"}, {"stop", NO_ARGS, NULL, 's', arg_none, APTR(&G.stop), "stop motor"},
@ -61,9 +63,10 @@ myoption cmdlnopts[] = {
{"eswstate",NO_ARGS, NULL, 'e', arg_none, APTR(&G.showesw), "show end-switches state"}, {"eswstate",NO_ARGS, NULL, 'e', arg_none, APTR(&G.showesw), "show end-switches state"},
{"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logname), "logfile name and path"}, {"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logname), "logfile name and path"},
{"server", NO_ARGS, NULL, 'S', arg_none, APTR(&G.server), "work as server"}, {"server", NO_ARGS, NULL, 'S', arg_none, APTR(&G.server), "work as server"},
{"port", NEED_ARG, NULL, 'p', arg_string, APTR(&G.port), "server port number"}, {"port", NEED_ARG, NULL, 'P', arg_string, APTR(&G.port), "server port number (default: " DEFPORT ")"},
{"host", NEED_ARG, NULL, 'H', arg_string, APTR(&G.host), "host to connect (default: localhost)"}, {"host", NEED_ARG, NULL, 'H', arg_string, APTR(&G.host), "host to connect (default: localhost)"},
{"standalone",NO_ARGS, NULL, 'A', arg_none, APTR(&G.standalone),"run as standalone application"}, {"standalone",NO_ARGS, NULL, 'A', arg_none, APTR(&G.standalone),"run as standalone application"},
{"pidfile", NEED_ARG, NULL, 'p', arg_string, APTR(&G.pidfilename),"name of PID-file (default: " DEFPIDNAME ")"},
end_option end_option
}; };

View File

@ -31,7 +31,6 @@ typedef struct{
int reset; // reset encoder int reset; // reset encoder
int verbose; // more messages int verbose; // more messages
int motorID; // motor address (from controller's settings) int motorID; // motor address (from controller's settings)
int bcastID; // broadcast motor address
double gotopos; // move focus to given position double gotopos; // move focus to given position
double targspeed; // just rotate motor with given speed double targspeed; // just rotate motor with given speed
int stop; // stop motor int stop; // stop motor
@ -42,6 +41,7 @@ typedef struct{
char *port; // port number for server or client char *port; // port number for server or client
char *host; // host to connect (in client mode) char *host; // host to connect (in client mode)
int standalone; // run standalone int standalone; // run standalone
char *pidfilename; // name of PID-file
} glob_pars; } glob_pars;

View File

@ -22,6 +22,7 @@
#include <signal.h> #include <signal.h>
#include "can_encoder.h" #include "can_encoder.h"
#include "canopen.h" #include "canopen.h"
#include "checkfile.h"
#include "cmdlnopts.h" #include "cmdlnopts.h"
#include "HW_dependent.h" #include "HW_dependent.h"
#include "socket.h" #include "socket.h"
@ -49,6 +50,7 @@ int verbose(const char *fmt, ...){
*/ */
void signals(int signo){ void signals(int signo){
WARNX("Received signal %d", signo); WARNX("Received signal %d", signo);
unlink_pidfile();
exit(signo); exit(signo);
} }
@ -87,26 +89,27 @@ int main (int argc, char *argv[]){
} }
signal(SIGTERM, signals); signal(SIGTERM, signals);
signal(SIGKILL, signals);
signal(SIGTSTP, SIG_IGN); signal(SIGTSTP, SIG_IGN);
signal(SIGHUP, SIG_IGN); signal(SIGHUP, SIG_IGN);
//can_dev[8] = '1'; //can_dev[8] = '1';
if(G->server || G->standalone){ // init hardware if(G->server || G->standalone){ // init hardware
check4running(G->pidfilename);
if(G->logname){ if(G->logname){
openlogfile(G->logname); openlogfile(G->logname);
} }
if(init_encoder(G->nodenum, G->reset)) ERRX("Encoder not found"); if(init_encoder(G->nodenum, G->reset)) ERRX("Encoder not found");
if(init_motor_ids(G->motorID)){
WARNX("Error during motor initialization");
ret = 1;
goto Oldcond;
}
if(getPos(&curposition)){ if(getPos(&curposition)){
WARNX("Can't read current position"); WARNX("Can't read current position");
ret = 1; ret = 1;
goto Oldcond; goto Oldcond;
}else verbose("Position @ start: %.2fmm\n", curposition); }else verbose("Position @ start: %.2fmm\n", curposition);
if(init_motor_ids(G->motorID)){
ret = 1;
goto Oldcond;
}
} }
if(G->server){ // daemonize & run server if(G->server){ // daemonize & run server
@ -157,17 +160,20 @@ int main (int argc, char *argv[]){
ret = move2pos(G->gotopos); ret = move2pos(G->gotopos);
goto Oldcond; goto Oldcond;
} }
double spd;
unsigned long pos;
Oldcond: Oldcond:
if(getPos(&curposition)) WARNX("Can't read current position"); if(get_pos_speed(&pos, &spd)) WARNX("Can't read current position");
else{ else{
if(G->verbose) printf("pos=%.2fmm, ", curposition); curposition = FOC_RAW2MM(pos);
else printf("%.2f\n", curposition); verbose("speed=%d\n", spd);
if(G->verbose) printf("pos=%.03fmm, ", curposition);
else printf("%.03f\n", curposition);
} }
if(G->showesw){ if(G->showesw){
eswstate e; eswstate e;
if(CAN_NOERR != get_endswitches(&e)) WARNX("Can't read end-switches state"); if(CAN_NOERR == get_endswitches(&e)) switch(e){
else switch(e){
case ESW_INACTIVE: case ESW_INACTIVE:
green("End-switches inactive\n"); green("End-switches inactive\n");
break; break;
@ -182,10 +188,6 @@ Oldcond:
red("ERROR: both end-switches active\n"); red("ERROR: both end-switches active\n");
} }
} }
double spd;
if(get_motor_speed(&spd) == CAN_NOERR) verbose("speed=%d\n", spd);
else WARNX("Can't read speed");
returnPreOper(); returnPreOper();
return ret; return ret;
} }

View File

@ -78,18 +78,25 @@
// Some parameters: indexes & subindexes // Some parameters: indexes & subindexes
// Digital inputs // Digital inputs
#define PAR_DI_SUBIDX 0 #define PAR_DI_SUBIDX 0
// inputs state (lowest bit is DI00) // inputs state (lowest bit is DI00), 0x208E
#define PAR_DIST_IDX 8334 #define PAR_DIST_IDX 8334
// Speed & current // Speed & current
#define PAR_SPD_SUBIDX 0 #define PAR_SPD_SUBIDX 0
#define PAR_CRNT_SUBIDX 0 #define PAR_CRNT_SUBIDX 0
// 0x207E - speed
#define PAR_SPD_IDX 8318 #define PAR_SPD_IDX 8318
// 0x2086 - current
#define PAR_CRNT_IDX 8326 #define PAR_CRNT_IDX 8326
// inputs role // inputs role
// 0x228c - DI0
#define PAR_DI00_IDX 8844 #define PAR_DI00_IDX 8844
// 0x2090
#define PAR_DI02_IDX 8336 #define PAR_DI02_IDX 8336
// 0x2091
#define PAR_DI03_IDX 8337 #define PAR_DI03_IDX 8337
// 0x2092
#define PAR_DI04_IDX 8338 #define PAR_DI04_IDX 8338
// 0x2093
#define PAR_DI05_IDX 8339 #define PAR_DI05_IDX 8339
// roles: // roles:
#define DI_NOFUNC 0 #define DI_NOFUNC 0

View File

@ -86,7 +86,7 @@ bool emerg_stop = FALSE;
static int send_data(int sock, int webquery, char *buf){ static int send_data(int sock, int webquery, char *buf){
if(!buf) return 0; if(!buf) return 0;
ssize_t L, Len = strlen(buf); ssize_t L, Len = strlen(buf);
DBG("buf: %s, Len: %zd", buf, Len); //DBG("buf: %s, Len: %zd", buf, Len);
if(Len < 1) return 0; if(Len < 1) return 0;
char tbuf[BUFLEN]; char tbuf[BUFLEN];
// OK buffer ready, prepare to send it // OK buffer ready, prepare to send it
@ -160,6 +160,30 @@ static const char *startmoving(double pos){
return S_ANS_OK; return S_ANS_OK;
} }
/**
* @brief ego, getoutESW - run go_out_from_ESW in a separate thread
*/
static void *ego(_U_ void *unused){
DBG("MOVE OUT FROM END-SWITCH");
pthread_mutex_lock(&canbus_mutex);
go_out_from_ESW();
pthread_mutex_unlock(&canbus_mutex);
pthread_mutex_unlock(&moving_mutex);
pthread_exit(NULL);
return NULL;
}
static void getoutESW(){
pthread_mutex_lock(&moving_mutex);
pthread_t m_thread;
if(pthread_create(&m_thread, NULL, ego, NULL)){
WARN("pthread_create()");
pthread_mutex_unlock(&moving_mutex);
}else{
DBG("Thread created, detouch");
pthread_detach(m_thread); // don't care about thread state
}
}
static void *handle_socket(void *asock){ static void *handle_socket(void *asock){
#define getparam(x) (strncmp(found, x, sizeof(x)-1) == 0) #define getparam(x) (strncmp(found, x, sizeof(x)-1) == 0)
//putlog("handle_socket(): getpid: %d, pthread_self: %lu, tid: %lu",getpid(), pthread_self(), syscall(SYS_gettid)); //putlog("handle_socket(): getpid: %d, pthread_self: %lu, tid: %lu",getpid(), pthread_self(), syscall(SYS_gettid));
@ -170,14 +194,14 @@ static void *handle_socket(void *asock){
double t0 = dtime(); double t0 = dtime();
while(dtime() - t0 < SOCKET_TIMEOUT){ while(dtime() - t0 < SOCKET_TIMEOUT){
if(!waittoread(sock)){ // no data incoming if(!waittoread(sock)){ // no data incoming
DBG("no incoming data"); //DBG("no incoming data");
continue; continue;
} }
if((rd = read(sock, buff, BUFLEN-1)) < 1){ if((rd = read(sock, buff, BUFLEN-1)) < 1){
DBG("socket closed. Exit"); //DBG("socket closed. Exit");
break; break;
} }
DBG("Got %zd bytes", rd); //DBG("Got %zd bytes", rd);
// add trailing zero to be on the safe side // add trailing zero to be on the safe side
buff[rd] = 0; buff[rd] = 0;
// now we should check what do user want // now we should check what do user want
@ -189,10 +213,10 @@ static void *handle_socket(void *asock){
// web query have format GET /some.resource // web query have format GET /some.resource
} }
// here we can process user data // here we can process user data
DBG("user send: %s%s\n", buff, webquery ? ", web" : ""); //DBG("user send: %s%s\n", buff, webquery ? ", web" : "");
// empty request == focus request // empty request == focus request
if(strlen(found) < 1 || getparam(S_CMD_FOCUS)){ if(strlen(found) < 1 || getparam(S_CMD_FOCUS)){
DBG("position request"); //DBG("position request");
snprintf(buff, BUFLEN, "%.03f", curPos()); snprintf(buff, BUFLEN, "%.03f", curPos());
}else if(getparam(S_CMD_STOP)){ }else if(getparam(S_CMD_STOP)){
DBG("Stop request"); DBG("Stop request");
@ -232,11 +256,8 @@ static void *handle_socket(void *asock){
case STAT_OK: case STAT_OK:
msg = S_STATUS_OK; msg = S_STATUS_OK;
break; break;
case STAT_BADESW: case STAT_DAMAGE:
msg = S_STATUS_BADESW; msg = S_STATUS_DAMAGE;
break;
case STAT_BOTHESW:
msg = S_STATUS_BOTHESW;
break; break;
case STAT_ERROR: case STAT_ERROR:
msg = S_STATUS_ERROR; msg = S_STATUS_ERROR;
@ -247,6 +268,11 @@ static void *handle_socket(void *asock){
case STAT_GOFROMESW: case STAT_GOFROMESW:
msg = S_STATUS_GOFROMESW; msg = S_STATUS_GOFROMESW;
break; break;
case STAT_FORBIDDEN:
msg = S_STATUS_FORBIDDEN;
break;
default:
msg = "Unknown status";
} }
sprintf(buff, msg); sprintf(buff, msg);
}else sprintf(buff, S_ANS_ERR); }else sprintf(buff, S_ANS_ERR);
@ -255,7 +281,7 @@ static void *handle_socket(void *asock){
} }
} }
close(sock); close(sock);
DBG("closed"); //DBG("closed");
//putlog("socket closed, exit"); //putlog("socket closed, exit");
pthread_exit(NULL); pthread_exit(NULL);
return NULL; return NULL;
@ -286,14 +312,13 @@ static void *server(void *asock){
struct in_addr ipAddr = pV4Addr->sin_addr; struct in_addr ipAddr = pV4Addr->sin_addr;
char str[INET_ADDRSTRLEN]; char str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN); inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN);
//putlog("get connection from %s", str); //DBG("Got connection from %s", str);
DBG("Got connection from %s", str);
pthread_t handler_thread; pthread_t handler_thread;
if(pthread_create(&handler_thread, NULL, handle_socket, (void*) &newsock)){ if(pthread_create(&handler_thread, NULL, handle_socket, (void*) &newsock)){
putlog("server(): pthread_create() failed"); putlog("server(): pthread_create() failed");
WARN("pthread_create()"); WARN("pthread_create()");
}else{ }else{
DBG("Thread created, detouch"); //DBG("Thread created, detouch");
pthread_detach(handler_thread); // don't care about thread state pthread_detach(handler_thread); // don't care about thread state
} }
} }
@ -322,13 +347,11 @@ static void daemon_(int sock){
// get current position // get current position
if(!pthread_mutex_trylock(&canbus_mutex)){ if(!pthread_mutex_trylock(&canbus_mutex)){
getPos(NULL); getPos(NULL);
if(get_status() != STAT_OK){ sysstatus st = get_status();
if(!pthread_mutex_trylock(&moving_mutex)){
go_out_from_ESW();
pthread_mutex_unlock(&moving_mutex);
}
}
pthread_mutex_unlock(&canbus_mutex); pthread_mutex_unlock(&canbus_mutex);
if(st != STAT_OK){
getoutESW();
}
} }
}while(1); }while(1);
putlog("daemon_(): UNREACHABLE CODE REACHED!"); putlog("daemon_(): UNREACHABLE CODE REACHED!");

View File

@ -46,11 +46,11 @@
// statuses // statuses
#define S_STATUS_OK "OK" #define S_STATUS_OK "OK"
#define S_STATUS_ESW "End-switch active" #define S_STATUS_ESW "End-switch active"
#define S_STATUS_ERROR "Uncoverable error" #define S_STATUS_ERROR "Erroneous state"
#define S_STATUS_BOTHESW "Both end-switches active"
#define S_STATUS_BADESW "Wrong end-switch active"
#define S_STATUS_ESW "End-switch active" #define S_STATUS_ESW "End-switch active"
#define S_STATUS_GOFROMESW "Moving from end-switch" #define S_STATUS_GOFROMESW "Moving from end-switch"
#define S_STATUS_FORBIDDEN "Motion in forbidden position"
#define S_STATUS_DAMAGE "The focuser damaged and can't work further"
bool emerg_stop; bool emerg_stop;