Instrument Neutral Distributed Interface INDI  1.9.5
arduino_st4.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2018 Jasem Mutlaq. All rights reserved.
3 
4  Arduino ST4 Driver.
5 
6  For this project: https://github.com/kevinferrare/arduino-st4
7 
8  This program is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by the Free
10  Software Foundation; either version 2 of the License, or (at your option)
11  any later version.
12 
13  This program is distributed in the hope that it will be useful, but WITHOUT
14  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16  more details.
17 
18  You should have received a copy of the GNU Library General Public License
19  along with this library; see the file COPYING.LIB. If not, write to
20  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  Boston, MA 02110-1301, USA.
22 
23  The full GNU General Public License is included in this distribution in the
24  file called LICENSE.
25 *******************************************************************************/
26 
27 #include "arduino_st4.h"
28 
29 #include "indicom.h"
31 
32 #include <cerrno>
33 #include <cstring>
34 #include <memory>
35 #include <termios.h>
36 #include <sys/ioctl.h>
37 
38 // We declare an auto pointer to ArduinoST4.
39 std::unique_ptr<ArduinoST4> arduinoST4(new ArduinoST4());
40 
41 #define FLAT_TIMEOUT 3
42 
44 {
45  setVersion(1, 0);
46 }
47 
49 {
51 
53 
55 
57 
58  serialConnection = new Connection::Serial(this);
59  serialConnection->registerHandshake([&]() { return Handshake(); });
61  // Arduino default port
62  serialConnection->setDefaultPort("/dev/ttyACM0");
63  registerConnection(serialConnection);
64 
65  return true;
66 }
67 
69 {
71 
72  if (isConnected())
73  {
76  }
77  else
78  {
81  }
82 
83  return true;
84 }
85 
87 {
88  return static_cast<const char *>("Arduino ST4");
89 }
90 
91 bool ArduinoST4::Handshake()
92 {
93  if (isSimulation())
94  {
95  LOGF_INFO("Connected successfuly to simulated %s.", getDeviceName());
96  return true;
97  }
98 
99  PortFD = serialConnection->getPortFD();
100 
101  return true;
102 }
103 
105 {
106  sendCommand("DISCONNECT#");
107 
109 }
110 
111 bool ArduinoST4::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
112 {
113  if (!strcmp(name, GuideNSNP.name) || !strcmp(name, GuideWENP.name))
114  {
115  processGuiderProperties(name, values, names, n);
116  return true;
117  }
118 
119  return INDI::DefaultDevice::ISNewNumber(dev, name, values, names, n);
120 }
121 
123 {
124  LOGF_DEBUG("Guiding: N %.0f ms", ms);
125 
126  if (GuideNSTID)
127  {
128  IERmTimer(GuideNSTID);
129  GuideNSTID = 0;
130  }
131 
132  if (sendCommand("DEC+#") == false)
133  return IPS_ALERT;
134 
135  guideDirection = ARD_N;
136  GuideNSTID = IEAddTimer(static_cast<int>(ms), guideTimeoutHelperN, this);
137  return IPS_BUSY;
138 }
139 
141 {
142  LOGF_DEBUG("Guiding: S %.0f ms", ms);
143 
144  if (GuideNSTID)
145  {
146  IERmTimer(GuideNSTID);
147  GuideNSTID = 0;
148  }
149 
150  if (sendCommand("DEC-#") == false)
151  return IPS_ALERT;
152 
153  guideDirection = ARD_S;
154  GuideNSTID = IEAddTimer(static_cast<int>(ms), guideTimeoutHelperS, this);
155  return IPS_BUSY;
156 }
157 
159 {
160  LOGF_DEBUG("Guiding: E %.0f ms", ms);
161 
162  if (GuideWETID)
163  {
164  IERmTimer(GuideWETID);
165  GuideWETID = 0;
166  }
167 
168  if (sendCommand("RA+#") == false)
169  return IPS_ALERT;
170 
171  guideDirection = ARD_E;
172  GuideWETID = IEAddTimer(static_cast<int>(ms), guideTimeoutHelperE, this);
173  return IPS_BUSY;
174 }
175 
177 {
178  LOGF_DEBUG("Guiding: W %.0f ms", ms);
179 
180  if (GuideWETID)
181  {
182  IERmTimer(GuideWETID);
183  GuideWETID = 0;
184  }
185 
186  if (sendCommand("RA-#") == false)
187  return IPS_ALERT;
188 
189  guideDirection = ARD_W;
190  GuideWETID = IEAddTimer(static_cast<int>(ms), guideTimeoutHelperE, this);
191  return IPS_BUSY;
192 }
193 
194 //GUIDE The timer helper functions.
196 {
197  static_cast<ArduinoST4 *>(p)->guideTimeout(ARD_N);
198 }
200 {
201  static_cast<ArduinoST4 *>(p)->guideTimeout(ARD_S);
202 }
204 {
205  static_cast<ArduinoST4 *>(p)->guideTimeout(ARD_W);
206 }
208 {
209  static_cast<ArduinoST4 *>(p)->guideTimeout(ARD_E);
210 }
211 
213 {
214  if (direction == ARD_N || direction == ARD_S)
215  {
216  if (sendCommand("DEC0#"))
217  {
218  GuideNSNP.s = IPS_IDLE;
219  LOG_DEBUG("Guiding: DEC axis stopped.");
220  }
221  else
222  {
224  LOG_ERROR("Failed to stop DEC axis.");
225  }
226 
227  GuideNSTID = 0;
228  GuideNSNP.np[0].value = 0;
229  GuideNSNP.np[1].value = 0;
230  IDSetNumber(&GuideNSNP, nullptr);
231  }
232 
233  if (direction == ARD_W || direction == ARD_E)
234  {
235  if (sendCommand("RA0#"))
236  {
237  GuideWENP.s = IPS_IDLE;
238  LOG_DEBUG("Guiding: RA axis stopped.");
239  }
240  else
241  {
242  LOG_ERROR("Failed to stop RA axis.");
244  }
245 
246  GuideWENP.np[0].value = 0;
247  GuideWENP.np[1].value = 0;
248  GuideWETID = 0;
249  IDSetNumber(&GuideWENP, nullptr);
250  }
251 }
252 
253 bool ArduinoST4::sendCommand(const char *cmd)
254 {
255  int nbytes_read=0, nbytes_written=0, tty_rc = 0;
256  char res[8] = {0};
257  LOGF_DEBUG("CMD <%s>", cmd);
258 
259  if (!isSimulation())
260  {
261  tcflush(PortFD, TCIOFLUSH);
262  if ( (tty_rc = tty_write_string(PortFD, cmd, &nbytes_written)) != TTY_OK)
263  {
264  char errorMessage[MAXRBUF];
265  tty_error_msg(tty_rc, errorMessage, MAXRBUF);
266  LOGF_ERROR("Serial write error: %s", errorMessage);
267  return false;
268  }
269  }
270 
271  if (isSimulation())
272  {
273  strncpy(res, "OK#", 8);
274  nbytes_read = 3;
275  }
276  else
277  {
278  if ( (tty_rc = tty_read_section(PortFD, res, '#', ARDUINO_TIMEOUT, &nbytes_read)) != TTY_OK)
279  {
280  char errorMessage[MAXRBUF];
281  tty_error_msg(tty_rc, errorMessage, MAXRBUF);
282  LOGF_ERROR("Serial read error: %s", errorMessage);
283  return false;
284  }
285  }
286 
287  res[nbytes_read - 1] = '\0';
288  LOGF_DEBUG("RES <%s>", res);
289 
290  return true;
291 }
cmd
__u8 cmd[4]
Definition: pwc-ioctl.h:4
ArduinoST4::guideTimeoutHelperE
static void guideTimeoutHelperE(void *p)
Definition: arduino_st4.cpp:207
INDI::DefaultDevice::addAuxControls
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
Definition: defaultdevice.cpp:665
IPState
IPState
Property state.
Definition: indiapi.h:158
LOGF_ERROR
#define LOGF_ERROR(fmt,...)
Definition: indilogger.h:80
_INumberVectorProperty::s
IPState s
Definition: indiapi.h:332
indicom.h
Implementations for common driver routines.
MOTION_TAB
const char * MOTION_TAB
MOTION_TAB Where all the motion control properties of the device are located.
Definition: defaultdevice.cpp:36
INDI::BaseDevice::GUIDER_INTERFACE
@ GUIDER_INTERFACE
Definition: basedevice.h:74
ArduinoST4::initProperties
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: arduino_st4.cpp:48
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
INDI::GuiderInterface::GuideWENP
INumberVectorProperty GuideWENP
Definition: indiguiderinterface.h:113
Connection::Serial
The Serial class manages connection with serial devices including Bluetooth. Serial communication is ...
Definition: connectionserial.h:56
INDI::DefaultDevice::isSimulation
bool isSimulation() const
Definition: defaultdevice.cpp:734
INDI::DefaultDevice::defineProperty
void defineProperty(INumberVectorProperty *property)
Definition: defaultdevice.cpp:997
ArduinoST4::GuideWest
virtual IPState GuideWest(uint32_t ms) override
Guide west for ms milliseconds. West is defined as RA-.
Definition: arduino_st4.cpp:176
INDI::DefaultDevice::setVersion
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
Definition: defaultdevice.cpp:1219
INDI::BaseDevice::getDeviceName
const char * getDeviceName() const
Definition: basedevice.cpp:799
ArduinoST4::ArduinoST4
ArduinoST4()
Definition: arduino_st4.cpp:43
INDI::GuiderInterface::initGuiderProperties
void initGuiderProperties(const char *deviceName, const char *groupName)
Initilize guider properties. It is recommended to call this function within initProperties() of your ...
Definition: indiguiderinterface.cpp:36
tty_read_section
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:557
ArduinoST4::ARDUINO_DIRECTION
ARDUINO_DIRECTION
Definition: arduino_st4.h:43
MAXRBUF
#define MAXRBUF
Definition: indidriver.c:52
INDI::DefaultDevice::initProperties
virtual bool initProperties()
Initilize properties initial state and value. The child class must implement this function.
Definition: defaultdevice.cpp:917
tty_error_msg
void tty_error_msg(int err_code, char *err_msg, int err_msg_len)
Retrieve the tty error message.
Definition: indicom.c:1156
Connection::Serial::setDefaultPort
void setDefaultPort(const char *port)
setDefaultPort Set default port. Call this function in initProperties() of your driver if you want to...
Definition: connectionserial.cpp:372
INDI::GuiderInterface::GuideNSNP
INumberVectorProperty GuideNSNP
Definition: indiguiderinterface.h:111
IEAddTimer
int IEAddTimer(int millisecs, IE_TCF *fp, void *p)
Register a new single-shot timer function, fp, to be called with ud as argument after ms.
Definition: eventloop.c:525
LOGF_DEBUG
#define LOGF_DEBUG(fmt,...)
Definition: indilogger.h:83
Connection::Serial::setDefaultBaudRate
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
Definition: connectionserial.cpp:381
Connection::Serial::B_57600
@ B_57600
Definition: connectionserial.h:82
ArduinoST4::ARD_W
@ ARD_W
Definition: arduino_st4.h:43
ArduinoST4::ARD_N
@ ARD_N
Definition: arduino_st4.h:43
INDI::DefaultDevice::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
Definition: defaultdevice.cpp:593
IPS_BUSY
@ IPS_BUSY
Definition: indiapi.h:162
connectionserial.h
_INumberVectorProperty::np
INumber * np
Definition: indiapi.h:334
IPS_IDLE
@ IPS_IDLE
Definition: indiapi.h:160
INDI::DefaultDevice::registerConnection
void registerConnection(Connection::Interface *newConnection)
registerConnection Add new connection plugin to the existing connection pool. The connection type sha...
Definition: defaultdevice.cpp:1107
arduinoST4
std::unique_ptr< ArduinoST4 > arduinoST4(new ArduinoST4())
_INumberVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:322
arduino_st4.h
INDI::BaseDevice::isConnected
bool isConnected() const
Definition: basedevice.cpp:518
ArduinoST4::getDefaultName
const char * getDefaultName() override
Definition: arduino_st4.cpp:86
GuiderInterface
Provides interface to implement guider (ST4) port functionality.
LOG_DEBUG
#define LOG_DEBUG(txt)
Definition: indilogger.h:75
ArduinoST4::GuideEast
virtual IPState GuideEast(uint32_t ms) override
Guide east for ms milliseconds. East is defined as RA+.
Definition: arduino_st4.cpp:158
LOGF_INFO
#define LOGF_INFO(fmt,...)
Definition: indilogger.h:82
LOG_ERROR
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
Definition: indilogger.h:72
ArduinoST4
Definition: arduino_st4.h:38
ArduinoST4::guideTimeoutHelperS
static void guideTimeoutHelperS(void *p)
Definition: arduino_st4.cpp:199
name
const char * name
Definition: indiserver.c:116
ArduinoST4::guideTimeoutHelperW
static void guideTimeoutHelperW(void *p)
Definition: arduino_st4.cpp:203
INDI
Namespace to encapsulate INDI client, drivers, and mediator classes.
Definition: AlignmentSubsystemForClients.cpp:11
ArduinoST4::Disconnect
virtual bool Disconnect() override
Disconnect from device.
Definition: arduino_st4.cpp:104
Connection::Interface::registerHandshake
void registerHandshake(std::function< bool()> callback)
registerHandshake Register a handshake function to be called once the intial connection to the device...
Definition: connectioninterface.cpp:108
ArduinoST4::ARD_E
@ ARD_E
Definition: arduino_st4.h:43
ArduinoST4::ARD_S
@ ARD_S
Definition: arduino_st4.h:43
ArduinoST4::ISNewNumber
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
Definition: arduino_st4.cpp:111
ArduinoST4::GuideSouth
virtual IPState GuideSouth(uint32_t ms) override
Guide south for ms milliseconds. South is defined as DEC-.
Definition: arduino_st4.cpp:140
Connection::Serial::getPortFD
int getPortFD() const
Definition: connectionserial.h:136
ArduinoST4::updateProperties
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: arduino_st4.cpp:68
INDI::BaseDevice::AUX_INTERFACE
@ AUX_INTERFACE
Definition: basedevice.h:87
INDI::DefaultDevice::Disconnect
virtual bool Disconnect()
Disconnect from device.
Definition: defaultdevice.cpp:1083
ArduinoST4::GuideNorth
virtual IPState GuideNorth(uint32_t ms) override
Guide north for ms milliseconds. North is defined as DEC+.
Definition: arduino_st4.cpp:122
tty_write_string
int tty_write_string(int fd, const char *buf, int *nbytes_written)
Writes a null terminated string to fd.
Definition: indicom.c:465
TTY_OK
@ TTY_OK
Definition: indicom.h:94
INDI::DefaultDevice::deleteProperty
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
Definition: defaultdevice.cpp:965
ArduinoST4::guideTimeoutHelperN
static void guideTimeoutHelperN(void *p)
Definition: arduino_st4.cpp:195
IDSetNumber
void void void IDSetNumber(const INumberVectorProperty *n, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing number vector property.
INDI::DefaultDevice::setDriverInterface
void setDriverInterface(uint16_t value)
setInterface Set driver interface. By default the driver interface is set to GENERAL_DEVICE....
Definition: defaultdevice.cpp:902
IERmTimer
void IERmTimer(int timerid)
Remove the timer with the given timerid, as returned from IEAddTimer() or IEAddPeriodicTimer().
Definition: eventloop.c:545
INDI::DefaultDevice::updateProperties
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: defaultdevice.cpp:890
INDI::GuiderInterface::processGuiderProperties
void processGuiderProperties(const char *name, double values[], char *names[], int n)
Call this function whenever client updates GuideNSNP or GuideWSP properties in the primary device....
Definition: indiguiderinterface.cpp:49
ArduinoST4::guideTimeout
void guideTimeout(ARDUINO_DIRECTION direction)
Definition: arduino_st4.cpp:212