another approach for 2step control

master
Steffen Pohle 1 year ago
parent 539e49b28f
commit d2378f014f

@ -50,8 +50,8 @@ enum {
POSCTL_MODE_OFF = 0,
POSCTL_MODE_CALIB,
POSCTL_MODE_CONTROL,
POSCTL_MODE_2STEPINIT,
POSCTL_MODE_2STEP
POSCTL_MODE_2STEPWAIT,
POSCTL_MODE_2STEPRUN
};
enum {
@ -73,6 +73,7 @@ enum {
struct PosCtl_2Step_Data {
int mode;
double pv[2];
double op[2];
double npv[2];
@ -150,8 +151,7 @@ class PosCtl {
void Stop ();
void StartCalibration ();
void StartControl ();
void Start2Step ();
void Stop2Step ();
void Run2Step ();
void Reset2Step ();
int GetMode () { return mode; };
void SetAxisParam (int axis, double min, double max, double k, double i, double d);

@ -202,7 +202,7 @@ G_MODULE_EXPORT void cb_posctl_btnsimreset (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_angles_draw (GtkWidget *area, cairo_t *cr, int w, int h, gpointer data);
G_MODULE_EXPORT void cb_posctl_axis_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data);
G_MODULE_EXPORT void cb_posctl_track_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data);
G_MODULE_EXPORT void cb_posctl_btn2stepstartstop (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_btn2steprun (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void cb_posctl_btn2stepreset (GtkWidget *widget, gpointer data);

@ -130,17 +130,9 @@ void cb_posctl_btnsetdest (GtkWidget *widget, gpointer data) {
/*
* calibrate adjust control output..
*/
void cb_posctl_btn2stepstartstop (GtkWidget *widget, gpointer data) {
void cb_posctl_btn2steprun (GtkWidget *widget, gpointer data) {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
GtkWidget *btn = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "posctl_btn_2stepctl"));
if (posctl.GetMode() == POSCTL_MODE_2STEP || posctl.GetMode() == POSCTL_MODE_2STEPINIT) {
posctl.Stop2Step();
gtk_button_set_label(GTK_BUTTON(btn), "Start");
}
else {
posctl.Start2Step();
gtk_button_set_label(GTK_BUTTON(btn), "Stop");
}
posctl.Run2Step();
};
@ -492,8 +484,7 @@ void cb_posctl_axis_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer da
/*
* add result to the table
*/
void posctl_2step_gui_update( double axis_pv[2], double axis_op[2],
double npv[2], double nop[2], double ppv[2], double pop[2]) {
void posctl_2step_gui_update(struct PosCtl_2Step_Data *d) {
GtkWidget *lramin = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "posctl_2s_ramin"));
GtkWidget *lramax = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "posctl_2s_ramax"));
@ -501,25 +492,28 @@ void posctl_2step_gui_update( double axis_pv[2], double axis_op[2],
GtkWidget *ldecmax = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "posctl_2s_decmax"));
GtkWidget *lraout = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "posctl_2s_raout"));
GtkWidget *ldecout = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "posctl_2s_decout"));
GtkWidget *btn = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "posctl_btn_2steprun"));
char txt[255];
if (d->mode == POSCTL_MODE_2STEPWAIT) gtk_widget_set_sensitive(btn, FALSE);
else gtk_widget_set_sensitive(btn, TRUE);
char txt[255];
// min
snprintf (txt, 255, "%2.5f [%2.5f]", npv[AXIS_RA], nop[AXIS_RA]);
snprintf (txt, 255, "%2.5f [%2.5f]", d->npv[AXIS_RA], d->nop[AXIS_RA]);
gtk_label_set_text(GTK_LABEL(lramin), txt);
snprintf (txt, 255, "%2.5f [%2.5f]", npv[AXIS_DEC], nop[AXIS_DEC]);
snprintf (txt, 255, "%2.5f [%2.5f]", d->npv[AXIS_DEC], d->nop[AXIS_DEC]);
gtk_label_set_text(GTK_LABEL(ldecmin), txt);
// max
snprintf (txt, 255, "%2.5f [%2.5f]", ppv[AXIS_RA], pop[AXIS_RA]);
snprintf (txt, 255, "%2.5f [%2.5f]", d->ppv[AXIS_RA], d->pop[AXIS_RA]);
gtk_label_set_text(GTK_LABEL(lramax), txt);
snprintf (txt, 255, "%2.5f [%2.5f]", ppv[AXIS_DEC], pop[AXIS_DEC]);
snprintf (txt, 255, "%2.5f [%2.5f]", d->ppv[AXIS_DEC], d->pop[AXIS_DEC]);
gtk_label_set_text(GTK_LABEL(ldecmax), txt);
// output
snprintf (txt, 255, "%2.5f [%2.5f]", axis_pv[AXIS_RA], axis_op[AXIS_RA]);
snprintf (txt, 255, "%2.5f [%2.5f]", d->pv[AXIS_RA], d->op[AXIS_RA]);
gtk_label_set_text(GTK_LABEL(lraout), txt);
snprintf (txt, 255, "%2.5f [%2.5f]", axis_pv[AXIS_DEC], axis_op[AXIS_DEC]);
snprintf (txt, 255, "%2.5f [%2.5f]", d->pv[AXIS_DEC], d->op[AXIS_DEC]);
gtk_label_set_text(GTK_LABEL(ldecout), txt);
cb_posctl_entryanglelen(NULL, NULL);
@ -576,10 +570,14 @@ void posctl_gui_update() {
GtkWidget *dec_pv = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "posctl_lb_d_dec"));
GtkWidget *pos_filter = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "posctl_entry_inputfilter"));
GtkWidget *btn = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "posctl_btn_2steprun"));
posctl.LockMutex();
int m = posctl.GetMode();
if (m == POSCTL_MODE_2STEPWAIT) gtk_widget_set_sensitive(btn, FALSE);
else gtk_widget_set_sensitive(btn, TRUE);
if (m == POSCTL_MODE_OFF) {
gtk_widget_set_sensitive(btnclib, true);
gtk_widget_set_sensitive(btncontrol, true);
@ -682,7 +680,7 @@ gboolean cb_thread_posctl_2step (gpointer data) {
posctl_gui_update();
if (data) {
posctl_2step_gui_update(d->pv, d->op, d->npv, d->nop, d->ppv, d->pop);
posctl_2step_gui_update(d);
free (data);
}
@ -792,6 +790,7 @@ void PosCtl::Stop() {
void PosCtl::NotifyGtk2Step() {
struct PosCtl_2Step_Data *data = (struct PosCtl_2Step_Data*) malloc (sizeof(struct PosCtl_2Step_Data));
data->mode = mode;
for (int i = 0; i < 2; i++) {
data->pv[i] = axis_pv[i];
data->op[i] = axis_op[i];
@ -1125,11 +1124,30 @@ void PosCtl::Loop (int pos_x, int pos_y, double dt) {
NotifyGtk();
}
else if (mode == POSCTL_MODE_2STEP || mode == POSCTL_MODE_2STEPINIT) {
LockMutex();
else if (mode == POSCTL_MODE_2STEPWAIT) {
//
// wait time CALIB_STARTSTOP_DELAY sec over?
struct timeval tv;
float timediff;
gettimeofday (&tv, NULL);
timediff = (float)(tv.tv_sec - calib_timestamp.tv_sec) + ((tv.tv_usec - calib_timestamp.tv_usec) / 1000000.0);
if (timediff > CALIB_STARTSTOP_DELAY) {
mode = POSCTL_MODE_2STEPRUN;
target_pos.x = pos.x;
target_pos.y = pos.y;
calib_timestamp = tv;
}
LockMutex();
NotifyGtk2Step();
UnLockMutex();
}
else if (mode == POSCTL_MODE_2STEPRUN) {
LockMutex();
NotifyGtk2Step();
UnLockMutex();
}
@ -1163,8 +1181,7 @@ void PosCtl::Reset2Step() {
nop[i] = NAN;
pop[i] = NAN;
}
posctl_2step_gui_update(axis_pv, axis_op, npv, nop, ppv, pop);
NotifyGtk2Step();
UnLockMutex();
NotifyGtk();
};
@ -1175,82 +1192,66 @@ void PosCtl::Reset2Step() {
* if npv and ppv == NAN set min pos for both axes
* min and max values will be read from the PID objects
*/
void PosCtl::Start2Step() {
int found1 = 0, found2 = 0, i;
void PosCtl::Run2Step() {
int allset = 0, i;
LockMutex();
for (i = 0, found2 = 0, found1 = 0; i < 2; i++) {
if (isnan(npv[i]) && isnan(ppv[i])) found1 = 1;
if (isnan(npv[i]) || isnan(ppv[i])) found2 = 1;
}
if (found1) {
mode = POSCTL_MODE_2STEPINIT;
for (i = 0; i < 2; i++) {
axis_op[i] = pid_axis[1-i].GetMin();
OutputWriteValue(i, axis_op[i]);
for (i = 0, allset = 1; i < 2; i++) {
if (isnan(npv[i]) || isnan(ppv[i])) allset = 0;
}
}
else if (found2) {
for (i = 0; i < 2; i++) {
axis_op[i] = pid_axis[1-i].GetMax();
OutputWriteValue(i, axis_op[i]);
}
mode = POSCTL_MODE_2STEPINIT;
}
else mode = POSCTL_MODE_2STEP;
target_pos = pos;
printf ("%s:%d %s axis_op: (%f %f)\n", __FILE__, __LINE__, __FUNCTION__, axis_op[0], axis_op[1]);
posctl_2step_gui_update(axis_pv, axis_op, npv, nop, ppv, pop);
UnLockMutex();
};
if (mode != POSCTL_MODE_2STEPRUN && mode != POSCTL_MODE_2STEPWAIT) {
//
// just start from the beginning
for (int i = 0; i < 2; i++) {
npv[i] = NAN;
ppv[i] = NAN;
nop[i] = NAN;
pop[i] = NAN;
}
target_pos = pos;
mode = POSCTL_MODE_2STEPWAIT;
/*
* with each cycle, caclulate an output between p and n values.
*/
void PosCtl::Stop2Step() {
double axisnew_op[2] = { NAN, NAN };
int i;
LockMutex();
OutputWriteStart();
OutputWriteValue(AXIS_DEC, pid_axis[AXIS_DEC].GetMin());
OutputWriteValue(AXIS_RA, pid_axis[AXIS_RA].GetMin());
gettimeofday (&calib_timestamp, NULL);
}
else if (mode == POSCTL_MODE_2STEPRUN) {
if (allset) {
//
// check if we got better values
for (int i = 0; i < 2; i++) {
if (axis_pv[i] < 0.0 && (isnan(npv[i]) || axis_pv[i] > npv[i])) {
npv[i] = axis_pv[i];
nop[i] = axis_op[i];
// FIXME: need to finish what to do next
}
if (axis_pv[i] > 0.0 && (isnan(ppv[i]) || axis_pv[i] < ppv[i])) {
ppv[i] = axis_pv[i];
pop[i] = axis_op[i];
else {
//
// one value still missing: set nXX and pXX and go to maximum output
for (int i = 0; i < 2; i++) {
ppv[i] = npv[i] = axis_pv[i];
pop[i] = nop[i] = axis_op[i];
}
OutputWriteStart();
OutputWriteValue(AXIS_DEC, pid_axis[AXIS_DEC].GetMax());
OutputWriteValue(AXIS_RA, pid_axis[AXIS_RA].GetMax());
}
// need to calculate new step
if (mode == POSCTL_MODE_2STEP) {
for (i = 0; i < 2; i++) {
axisnew_op[i] = (nop[i] + pop[i]) / 2.0;
OutputWriteValue(i, axisnew_op[i]);
target_pos = pos;
mode = POSCTL_MODE_2STEPWAIT;
gettimeofday (&calib_timestamp, NULL);
}
else {
printf ("%s:%d %s ERROR: something went wrong. Mode not correct.\n", __FILE__, __LINE__, __FUNCTION__);
}
printf ("%s:%d %s axis \t_op:\t%f\t%f \t_pv:\t%f\t%f \t new:\t%f\t%f\n", __FILE__, __LINE__, __FUNCTION__,
axis_op[0], axis_op[1], axis_pv[0], axis_pv[1], axisnew_op[0], axisnew_op[1]);
mode = POSCTL_MODE_OFF;
posctl_2step_gui_update(axis_pv, axis_op, npv, nop, ppv, pop);
for (i = 0; i < 2; i++) axis_op[i] = axisnew_op[i];
printf ("%s:%d %s axis_op: (%f %f)\n", __FILE__, __LINE__, __FUNCTION__, axis_op[0], axis_op[1]);
NotifyGtk2Step();
UnLockMutex();
};
void PosCtl::SetDevice (std::string d) {
printf ("%s:%d %s new device:%s\n", __FILE__, __LINE__, __FUNCTION__, d.c_str());
@ -1392,6 +1393,10 @@ int PosCtl::ReadTTY (char * inbuf, int length) {
return 0;
}
/*
* write output, and save last set value in axis_op
*/
int PosCtl::OutputWriteValue (int axis, double value) {
char outbuf[255];
@ -1419,6 +1424,8 @@ int PosCtl::OutputWriteValue (int axis, double value) {
WriteTTY(outbuf);
ReadTTY(outbuf, sizeof(outbuf) - 1);
axis_op[axis] = value;
return 0;
};

@ -487,6 +487,11 @@
<property name="can-focus">False</property>
<property name="stock">gtk-close</property>
</object>
<object class="GtkImage" id="image_calc">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="stock">gtk-refresh</property>
</object>
<object class="GtkImage" id="image_control">
<property name="visible">True</property>
<property name="can-focus">False</property>
@ -502,6 +507,11 @@
<property name="can-focus">False</property>
<property name="stock">gtk-refresh</property>
</object>
<object class="GtkImage" id="image_reset">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="stock">gtk-cancel</property>
</object>
<object class="GtkWindow" id="window-posctl">
<property name="can-focus">False</property>
<property name="border-width">4</property>
@ -1992,6 +2002,8 @@
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="image">image_reset</property>
<property name="always-show-image">True</property>
<signal name="activate" handler="cb_posctl_btn2stepreset" swapped="no"/>
<signal name="pressed" handler="cb_posctl_btn2stepreset" swapped="no"/>
</object>
@ -2002,13 +2014,15 @@
</packing>
</child>
<child>
<object class="GtkButton" id="posctl_btn_2stepctl">
<property name="label" translatable="yes">Start</property>
<object class="GtkButton" id="posctl_btn_2steprun">
<property name="label" translatable="yes">Run</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="activate" handler="cb_posctl_btn2stepstartstop" swapped="no"/>
<signal name="pressed" handler="cb_posctl_btn2stepstartstop" swapped="no"/>
<property name="image">image_calc</property>
<property name="always-show-image">True</property>
<signal name="activate" handler="cb_posctl_btn2steprun" swapped="no"/>
<signal name="pressed" handler="cb_posctl_btn2steprun" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>

Loading…
Cancel
Save