Instrument Neutral Distributed Interface INDI  2.0.2
wanderer_rotator_lite.cpp
Go to the documentation of this file.
1 /*
2  WandererAstro WandererRotatorLite
3  Copyright (C) 2022 Frank Wang (1010965596@qq.com)
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 */
20 
21 #include "wanderer_rotator_lite.h"
22 #include "indicom.h"
24 #include <cmath>
25 #include <cstring>
26 #include <memory>
27 #include <termios.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <sstream>
31 #include <iostream>
32 
33 
34 // We declare an auto pointer to WandererRotatorLite.
35 static std::unique_ptr<WandererRotatorLite> RotatorLite(new WandererRotatorLite());
36 
38 {
39  setVersion(1, 0);
41 }
43 {
47  IUFillSwitch(&HomeS[0], "SetHomeButton", "Set Current Position as Home", ISS_OFF);
48  IUFillSwitchVector(&HomeSP, HomeS, 1, getDeviceName(), "SetHome", "Set Home", MAIN_CONTROL_TAB, IP_RW, ISR_ATMOST1, 5,
49  IPS_IDLE);
50 
51  return true;
52 }
53 
55 {
57 
58  if (isConnected())
59  {
60 
61  defineProperty(&HomeSP);
64  }
65  else
66  {
67  deleteProperty(HomeSP.name);
70  }
71  return true;
72 }
73 
74 bool WandererRotatorLite::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
75 {
76  if (dev && !strcmp(dev, getDeviceName()))
77  {
78  if (!strcmp(name, HomeSP.name))
79  {
80 
81  HomeSP.s = SetHomePosition() ? IPS_OK : IPS_ALERT;
82  GotoRotatorN[0].value = 0;
83  LOG_INFO("Home is set");
84  IDSetSwitch(&HomeSP, nullptr);
85  IDSetNumber(&GotoRotatorNP, nullptr);
86  return true;
87 
88  }
89  if (!strcmp(name, HomeRotatorSP.name))
90  {
91 
93  LOG_INFO("Homing....");
94  IDSetSwitch(&HomeRotatorSP, nullptr);
95  return true;
96 
97  }
98  }
99 
100  return Rotator::ISNewSwitch(dev, name, states, names, n);
101 }
102 
103 
104 
106 {
107  return "WandererRotatorLite";
108 }
113 bool WandererRotatorLite::Handshake()
114 {
115  tcflush(PortFD, TCIOFLUSH);
116  int nbytes_read1 = 0, nbytes_written = 0, rc = -1;
117  int nbytes_read2 = 0;
118  int nbytes_read3 = 0;
119  char res1[64] = {0};
120  char res2[64] = {0};
121  char res3[64] = {0};
122  LOGF_DEBUG("CMD <%s>", "150001");
123  if ((rc = tty_write_string(PortFD, "1500001", &nbytes_written)) != TTY_OK)
124  {
125  char errorMessage[MAXRBUF];
126  tty_error_msg(rc, errorMessage, MAXRBUF);
127  LOGF_ERROR("Serial write error: %s", errorMessage);
128  return false;
129  }
130 
131  if ((rc = tty_read_section(PortFD, res1, 'A', 5, &nbytes_read1)) != TTY_OK)
132  {
133  char errorMessage[MAXRBUF];
134  tty_error_msg(rc, errorMessage, MAXRBUF);
135  LOGF_ERROR("Device read error: %s", errorMessage);
136  return false;
137  }
138  if ((rc = tty_read_section(PortFD, res2, 'A', 5, &nbytes_read2)) != TTY_OK)
139  {
140  char errorMessage[MAXRBUF];
141  tty_error_msg(rc, errorMessage, MAXRBUF);
142  LOGF_ERROR("Firmware read error: %s", errorMessage);
143  return false;
144  }
145  if ((rc = tty_read_section(PortFD, res3, 'A', 5, &nbytes_read3)) != TTY_OK)
146  {
147  char errorMessage[MAXRBUF];
148  tty_error_msg(rc, errorMessage, MAXRBUF);
149  LOGF_ERROR("Position read error: %s", errorMessage);
150  return false;
151  }
152  if(atof(res3) >= 100000)
153  {
154  GotoRotatorN[0].value = (atof(res3) - 100000) / 100;
155  }
156  else
157  {
158  GotoRotatorN[0].value = atof(res3) / 100;
159  }
160  res1[nbytes_read1 - 1] = '\0';
161  res2[nbytes_read2 - 1] = '\0';
162  res3[nbytes_read3 - 1] = '\0';
163  LOGF_DEBUG("RES <%s>", res1);
164  LOGF_INFO("Handshake successful:%s", res1);
165  LOGF_INFO("Firmware Version:%s", res2);
166  tcflush(PortFD, TCIOFLUSH);
167  return true;
168 }
169 
175 
177 {
178  backlashcompensation = 0;
179  angle = angle - GotoRotatorN[0].value;
180  if (angle * positionhistory < 0 && angle > 0)
181  {
182  angle = angle + backlash;
183  backlashcompensation = -1 * backlash;
184  }
185  if (angle * positionhistory < 0 && angle < 0)
186  {
187  angle = angle - backlash;
188  backlashcompensation = backlash;
189  }
190  char cmd[16];
191  int position = (int)(reversecoefficient * angle * 1155);
192  positionhistory = angle;
193  snprintf(cmd, 16, "%d", position);
194  Move(cmd);
195  return IPS_BUSY;
196 }
197 
201 
203 {
204 
205  haltcommand = true;
206  positioncount = 0;
207  SetTimer(10);
208  int nbytes_read1 = 0, nbytes_written = 0, rc = -1;
209  int nbytes_read2 = 0;
210  char res1[16] = {0};
211  char res2[16] = {0};
212  tcflush(PortFD, TCIOFLUSH);
213  if ((rc = tty_write_string(PortFD, "Stop", &nbytes_written)) != TTY_OK)
214  {
215  char errorMessage[MAXRBUF];
216  tty_error_msg(rc, errorMessage, MAXRBUF);
217  LOGF_ERROR("Serial write error: %s", errorMessage);
218  return false;
219  }
220 
221  if ((rc = tty_read_section(PortFD, res1, 'A', 5, &nbytes_read1)) != TTY_OK)
222  {
223  char errorMessage[MAXRBUF];
224  tty_error_msg(rc, errorMessage, MAXRBUF);
225  LOGF_ERROR("Relative position read error: %s", errorMessage);
226  return false;
227  }
228  if ((rc = tty_read_section(PortFD, res2, 'A', 5, &nbytes_read2)) != TTY_OK)
229  {
230  char errorMessage[MAXRBUF];
231  tty_error_msg(rc, errorMessage, MAXRBUF);
232  LOGF_ERROR("Mechanical position read error: %s", errorMessage);
233  return false;
234  }
235  else
236  {
237  haltcommand = false;
238  }
239  GotoRotatorN[0].value = atof(res2) / 100;
240  res1[nbytes_read1 - 1] = '\0';
241  res2[nbytes_read2 - 1] = '\0';
242  LOGF_DEBUG("Move Relative:%s", res1);
243  LOGF_DEBUG("Move to Mechanical:%s", res2);
244  tcflush(PortFD, TCIOFLUSH);
245  return true;
246 }
247 
253 {
254 
255  double angle = -1 * reversecoefficient * GotoRotatorN[0].value;
256  positionhistory = angle;
257  char cmd[16];
258  int position = (int)(angle * 1155);
259  snprintf(cmd, 16, "%d", position);
260  Move(cmd);
261  return IPS_BUSY;
262 }
263 
270 {
271 
272  if (enabled)
273  {
274  reversecoefficient = -1;
275  ReverseState = true;
276  return true;
277  }
278 
279  else
280  {
281  reversecoefficient = 1;
282  ReverseState = false;
283  return true;
284  }
285  return false;
286 }
287 
291 
293 {
294 
295  if(haltcommand)
296  {
299  IDSetSwitch(&HomeRotatorSP, nullptr);
300  haltcommand = false;
301  positioncount = 0;
302  return;
303  }
304  if(positioncount > 0)
305  {
306  GotoRotatorN[0].value += reversecoefficient * abs(positionhistory) / positionhistory;
307  positioncount--;
308  IDSetNumber(&GotoRotatorNP, nullptr);
309  SetTimer(150);
310  return;
311  }
313  {
314  LOG_INFO("Done");
315  int nbytes_read1 = 0, rc = -1;
316  int nbytes_read2 = 0;
317  char res1[16] = {0};
318  char res2[16] = {0};
319 
320  if ((rc = tty_read_section(PortFD, res1, 'A', 5, &nbytes_read1)) != TTY_OK)
321  {
322  char errorMessage[MAXRBUF];
323  tty_error_msg(rc, errorMessage, MAXRBUF);
324  LOGF_ERROR("Relative position read error: %s", errorMessage);
325  return;
326  }
327  if ((rc = tty_read_section(PortFD, res2, 'A', 5, &nbytes_read2)) != TTY_OK)
328  {
329  char errorMessage[MAXRBUF];
330  tty_error_msg(rc, errorMessage, MAXRBUF);
331  LOGF_ERROR("Mechanical position read error: %s", errorMessage);
332  return;
333  }
334  GotoRotatorN[0].value = positiontemp + reversecoefficient * atof(res1) + backlashcompensation;
335 
338  IDSetNumber(&GotoRotatorNP, nullptr);
339  IDSetSwitch(&HomeRotatorSP, nullptr);
340  }
342 }
343 
349 
350 bool WandererRotatorLite::Move(const char *cmd)
351 {
352  positiontemp = GotoRotatorN[0].value;
353  int nbytes_written = 0, rc = -1;
354  LOGF_DEBUG("CMD <%s>", cmd);
355  positioncount = abs(atoi(cmd) / 1155);
356  if ((rc = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
357  {
358  char errorMessage[MAXRBUF];
359  tty_error_msg(rc, errorMessage, MAXRBUF);
360  LOGF_ERROR("Serial write error: %s", errorMessage);
361  return false;
362  }
363  usleep(1200000);
364  SetTimer(150);
365  return true;
366 }
367 
368 
374 
375 bool WandererRotatorLite::sendCommand(const char *cmd)
376 {
377  int nbytes_read = 0, nbytes_written = 0, rc = -1;
378  char res[32] = {0};
379  LOGF_DEBUG("CMD <%s>", cmd);
380 
381  tcflush(PortFD, TCIOFLUSH);
382  if ((rc = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
383  {
384  char errorMessage[MAXRBUF];
385  tty_error_msg(rc, errorMessage, MAXRBUF);
386  LOGF_ERROR("Serial write error: %s", errorMessage);
387  return false;
388  }
389 
390 
391  if ((rc = tty_read_section(PortFD, res, 'A', 60, &nbytes_read)) != TTY_OK)
392  {
393  char errorMessage[MAXRBUF];
394  tty_error_msg(rc, errorMessage, MAXRBUF);
395  LOGF_ERROR("Serial read error: %s", errorMessage);
396  return false;
397  }
398  tcflush(PortFD, TCIOFLUSH);
399  res[nbytes_read - 1] = '\0';
400  LOGF_DEBUG("RES <%s>", res);
401  return true;
402 }
403 
404 
409 bool WandererRotatorLite::SetHomePosition()
410 {
411  int nbytes_written = 0, rc = -1;
412  LOGF_DEBUG("CMD <%s>", "1500002");
413 
414  tcflush(PortFD, TCIOFLUSH);
415  if ((rc = tty_write_string(PortFD, "1500002", &nbytes_written)) != TTY_OK)
416  {
417  char errorMessage[MAXRBUF];
418  tty_error_msg(rc, errorMessage, MAXRBUF);
419  LOGF_ERROR("Serial write error: %s", errorMessage);
420  return false;
421  }
422 
423  tcflush(PortFD, TCIOFLUSH);
424  GotoRotatorN[0].value = 0;
425  return true;
426 }
433 {
434  backlash = (double)(steps / 1155);
435  return true;
436 }
443 {
444  if(enabled)
445  {
446  return SetRotatorBacklash(RotatorBacklashN[0].value);
447  }
448  else
449  {
450  return SetRotatorBacklash(0);
451  }
452 
453 }
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
INumberVectorProperty GotoRotatorNP
void SetCapability(uint32_t cap)
SetRotatorCapability sets the Rotator capabilities. All capabilities must be initialized.
ISwitchVectorProperty HomeRotatorSP
Connection::Serial * serialConnection
Definition: indirotator.h:95
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: indirotator.cpp:37
INumberVectorProperty PresetNP
Definition: indirotator.h:91
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: indirotator.cpp:94
ISwitchVectorProperty PresetGotoSP
Definition: indirotator.h:93
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
const char * getDefaultName() override
virtual void TimerHit() override
WandererRotatorLite::TimerHit.
virtual bool ReverseRotator(bool enabled) override
WandererRotatorLite::ReverseRotator.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
virtual IPState MoveRotator(double angle) override
WandererRotatorLite::MoveRotator.
virtual bool SetRotatorBacklashEnabled(bool enabled) override
WandererRotatorLite::SetRotatorBacklashEnabled.
virtual bool AbortRotator() override
WandererRotatorLite::AbortRotator.
virtual IPState HomeRotator() override
WandererRotatorLite::HomeRotator.
virtual bool SetRotatorBacklash(int32_t steps) override
WandererRotatorLite::SetRotatorBacklash.
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
void ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Update the value of an existing switch vector property.
ISState
Switch state.
Definition: indiapi.h:150
@ ISS_OFF
Definition: indiapi.h:151
@ IP_RW
Definition: indiapi.h:186
IPState
Property state.
Definition: indiapi.h:160
@ IPS_BUSY
Definition: indiapi.h:163
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
@ ISR_ATMOST1
Definition: indiapi.h:174
int tty_read_section(int fd, char *buf, char stop_char, int timeout, int *nbytes_read)
read buffer from terminal with a delimiter
Definition: indicom.c:566
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition: indicom.c:474
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition: indicom.c:1167
Implementations for common driver routines.
@ TTY_OK
Definition: indicom.h:150
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
Definition: indidevapi.c:158
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
Definition: indidevapi.c:235
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1211
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
Definition: indidriver.c:1231
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
#define LOG_INFO(txt)
Definition: indilogger.h:74
#define MAXRBUF
Definition: indiserver.cpp:102
__u8 cmd[4]
Definition: pwc-ioctl.h:2
char name[MAXINDINAME]
Definition: indiapi.h:323
char name[MAXINDINAME]
Definition: indiapi.h:371