63 stepsPerRevolution = ~0;
67 if (wordexp(
"~/.indi/ScopeDome_DomeInertia_Table.txt", &wexp, 0) == 0)
69 FILE *inertia = fopen(wexp.we_wordv[0],
"r");
73 fseek(inertia, 3, SEEK_SET);
77 while (fgets(line,
sizeof(line), inertia))
81 char* splitter = strchr(line,
';');
87 result = atoi(splitter);
90 inertiaTable.push_back(result);
96 LOGF_INFO(
"Read inertia file %s", wexp.we_wordv[0]);
100 LOG_WARN(
"Could not read inertia file, please generate one with Windows "
101 "driver setup and copy to "
102 "~/.indi/ScopeDome_DomeInertia_Table.txt");
192 stepsPerRevolution = interface->getStepsPerRevolution();
193 LOGF_INFO(
"Steps per revolution read as %d", stepsPerRevolution);
221 bool calibrationNeeded = interface->isCalibrationNeeded();
226 double fwMain, fwRotary;
227 interface->getFirmwareVersions(fwMain, fwRotary);
234 if(rotaryLinkEstablished ==
ISS_OFF)
236 LOG_WARN(
"Rotary link not established, shutter control not possible");
268 if (interface->detect())
272 LOG_ERROR(
"Can't identify the card, check card type and baud rate (115200 for USB Card 2.1, 9600 for Arduino Card)");
281 return (
const char *)
"ScopeDome Dome";
295 size_t numSensors = interface->getNumberOfSensors();
297 for(
size_t i = 0; i < numSensors; i++)
299 auto info = interface->getSensorInfo(i);
301 info.format.c_str(), info.minValue, info.maxValue, 1.0, 0.0);
308 size_t numRelays = interface->getNumberOfRelays();
310 for(
size_t i = 0; i < numRelays; i++)
312 auto info = interface->getRelayInfo(i);
321 size_t numInputs = interface->getNumberOfInputs();
323 for(
size_t i = 0; i < numInputs; i++)
325 auto info = interface->getInputInfo(i);
382 interface->findHome();
411 interface->calibrate();
419 for(
int i = 0; i < n; i++)
421 interface->setRelayState(i,
RelaysSP[i].getState());
454 LOG_DEBUG(
"Home sensor polarity set to ACTIVE_LOW");
459 LOG_DEBUG(
"Home sensor polarity set to ACTIVE_HIGH");
508 LOGF_ERROR(
"Error reading input state: %d", rc);
562 if (link != rotaryLinkEstablished)
564 rotaryLinkEstablished = link;
565 if(rotaryLinkEstablished ==
ISS_OFF)
567 LOG_WARN(
"Rotary link not established, shutter control not possible");
571 LOG_WARN(
"Rotary link established, shutter control now possible");
579 LOG_WARN(
"Retrying closing shutter");
584 LOG_WARN(
"Retrying opening shutter");
599 rotationCounter = interface->getRotationCounter();
603 double az = ((double)rotationCounter * -360.0 / stepsPerRevolution) +
DomeHomePositionNP[0].getValue();
604 az = fmod(az, 360.0);
610 LOGF_DEBUG(
"Dome position %f, step count %d", az, rotationCounter);
621 SensorsNP[i].setValue(interface->getSensorValue(i));
651 interface->updateState();
653 currentStatus = interface->getStatus();
684 interface->resetCounter();
702 currentRotation = interface->getRotationCounterExt();
703 LOGF_INFO(
"Current rotation is %d", currentRotation);
704 if (abs(currentRotation) < 100)
715 interface->move(currentRotation);
724 stepsPerRevolution = interface->getStepsPerRevolution();
725 LOGF_INFO(
"Calibration complete, steps per revolution read as %d", stepsPerRevolution);
757 LOG_INFO(
"Dome reached requested azimuth angle.");
794 static int tmpCounter = 0;
795 if (--tmpCounter <= 0)
827 return sendMove(azDiff);
836 return sendMove(azDiff);
842IPState ScopeDome::sendMove(
double azDiff)
846 int steps =
static_cast<int>(-azDiff * stepsPerRevolution / 360.0);
852 steps = compensateInertia(steps);
858 interface->move(-steps);
862 int steps =
static_cast<int>(azDiff * stepsPerRevolution / 360.0);
868 steps = compensateInertia(steps);
874 interface->move(steps);
938 LOGF_INFO(
"Control shutter %d", (
int)operation);
1013void ScopeDome::reconnect()
1016 LOG_INFO(
"Reconnecting serial port");
1017 reconnecting =
true;
1022 interface->setPortFD(
PortFD);
1024 reconnecting =
false;
1038static const float k0 = -5.8666426e3;
1039static const float k1 = 2.232870244e1;
1040static const float k2 = 1.39387003e-2;
1041static const float k3 = -3.4262402e-5;
1042static const float k4 = 2.7040955e-8;
1043static const float k5 = 6.7063522e-1;
1045static float pvsIce(
float T)
1047 float lnP = k0 / T + k1 + (k2 + (k3 + (k4 * T)) * T) * T + k5 *
log(T);
1063static const float n1 = 0.11670521452767e4;
1064static const float n6 = 0.14915108613530e2;
1065static const float n2 = -0.72421316703206e6;
1066static const float n7 = -0.48232657361591e4;
1067static const float n3 = -0.17073846940092e2;
1068static const float n8 = 0.40511340542057e6;
1069static const float n4 = 0.12020824702470e5;
1070static const float n9 = -0.23855557567849;
1071static const float n5 = -0.32325550322333e7;
1072static const float n10 = 0.65017534844798e3;
1074static float pvsWater(
float T)
1076 float th = T + n9 / (T - n10);
1077 float A = (
th + n1) *
th + n2;
1079 float B = (n3 *
th + n4) *
th + n5;
1080 float C = (n6 *
th + n7) *
th + n8;
1083 float p = 2.0f * C / (-B + sqrt(B * B - 4.0f * A * C));
1089static const float C_OFFSET = 273.15f;
1090static const float minT = 173;
1091static const float maxT = 678;
1093static float PVS(
float T)
1095 if (T < minT || T > maxT)
1097 else if (T < C_OFFSET)
1103static float solve(
float (*f)(
float),
float y,
float x0)
1108 while (++count < maxCount)
1111 float dx = x / 1000;
1113 xNew = x + dx * (y - z) / (f(x + dx) - z);
1114 if (fabs((xNew - x) / xNew) < 0.0001f)
1121float ScopeDome::getDewPoint(
float RH,
float T)
1124 return solve(PVS, RH / 100 * PVS(T), T) - C_OFFSET;
1127int ScopeDome::compensateInertia(
int steps)
1129 if (inertiaTable.size() == 0)
1135 for (uint16_t out = 0; out < inertiaTable.size(); out++)
1137 if (inertiaTable[out] > steps)
1139 LOGF_DEBUG(
"inertia %d -> %d", steps, out - 1);
1145 int lastEntry = inertiaTable.size() - 1;
1146 int inertia = inertiaTable[lastEntry] - lastEntry;
1147 int movement = steps - inertia;
1148 LOGF_DEBUG(
"inertia %d -> %d", steps, movement);
void log(const std::string &log)
void setDefaultBaudRate(BaudRate newRate)
setDefaultBaudRate Set default baud rate. The default baud rate is 9600 unless otherwise changed by t...
virtual bool Disconnect() override
Disconnect Disconnect from device.
virtual bool Connect() override
Connect Connect to device via the implemented communication medium. Do not perform any handshakes.
void setPollingPeriodRange(uint32_t minimum, uint32_t maximum)
setPollingPeriodRange Set the range permitted by the polling range in milliseconds
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.
bool isSimulation() const
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
Connection::Interface * getActiveConnection()
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
void SetParked(bool isparked)
SetParked Change the mount parking status. The data park file (stored in ~/.indi/ParkData....
void SetDomeCapability(uint32_t cap)
SetDomeCapability set the dome capabilities. All capabilities must be initialized.
void setDomeConnection(const uint8_t &value)
setDomeConnection Set Dome connection mode. Child class should call this in the constructor before Do...
INDI::PropertySwitch ShutterParkPolicySP
const char * GetShutterStatusString(ShutterState status)
getShutterStatusString
INDI::PropertyNumber DomeParamNP
ShutterState m_ShutterState
void SetAxis1Park(double value)
SetRAPark Set current AZ parking position. The data park file (stored in ~/.indi/ParkData....
void SetAxis1ParkDefault(double steps)
SetAxis1Park Set default AZ parking position.
ShutterOperation
Shutter operation command.
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
INDI::PropertyNumber DomeAbsPosNP
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Dome Presets in the configuration file
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
void setShutterState(const ShutterState &value)
void setDomeState(const DomeState &value)
bool InitPark()
InitPark Loads parking data (stored in ~/.indi/ParkData.xml) that contains parking status and parking...
Connection::Serial * serialConnection
void SetParkDataType(DomeParkData type)
setParkDataType Sets the type of parking data stored in the park data file and presented to the user.
INDI::PropertySwitch DomeShutterSP
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
DomeState getDomeState() const
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void save(FILE *f) const
save Save property to configuration file.
const char * getName() const
bool isNameMatch(const char *otherName) const
bool update(const double values[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
bool update(const ISState states[], const char *const names[], int n)
int findOnSwitchIndex() const
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
bool update(const char *const texts[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
friend class ScopeDomeUSB21
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
INDI::PropertySwitch DerotateSP
virtual const char * getDefaultName() override
virtual bool SetDefaultPark() override
SetDefaultPark Set default coordinates/encoders value as the desired parking position.
virtual void TimerHit() override
Callback function to be called once SetTimer duration elapses.
INDI::PropertyText CredentialsTP
ShutterState simShutterStatus
friend class ScopeDomeArduino
INDI::PropertySwitch FindHomeSP
ShutterOperation targetShutter
virtual bool SetCurrentPark() override
SetCurrentPark Set current coordinates/encoders value as the desired parking position.
INDI::PropertyNumber DomeHomePositionNP
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
bool UpdateSensorStatus()
INDI::PropertyNumber FirmwareVersionsNP
virtual IPState MoveRel(double azDiff) override
Move the Dome to an relative position.
virtual IPState ControlShutter(ShutterOperation operation) override
Open or Close shutter.
virtual IPState UnPark() override
UnPark dome. The action of the Unpark command is dome specific, but it may include opening the shutte...
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool Abort() override
Abort all dome motion.
INDI::PropertySwitch CardTypeSP
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
bool UpdateShutterStatus()
virtual bool Handshake() override
perform handshake with device to check communication
INDI::PropertySwitch StartCalibrationSP
INDI::PropertySwitch HomeSensorPolaritySP
INDI::PropertySwitch InputsSP
INDI::PropertySwitch RelaysSP
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Saves the Device Port and Dome Presets in the configuration file
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
INDI::PropertyNumber SensorsNP
virtual IPState MoveAbs(double az) override
Move the Dome to an absolute azimuth.
INDI::PropertyNumber StepsPerRevolutionNP
INDI::PropertySwitch CalibrationNeededSP
virtual IPState Move(DomeDirection dir, DomeMotionCommand operation) override
Move the Dome in a particular direction.
virtual IPState Park() override
Goto Park Position. The park position is an absolute azimuth value.
const char * CONNECTION_TAB
CONNECTION_TAB Where all device connection settings (serial, usb, ethernet) are defined and controlle...
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * INFO_TAB
INFO_TAB Where all the properties for general information are located.
const char * SITE_TAB
SITE_TAB Where all site information setting are located.
Implementations for common driver routines.
int IUGetConfigText(const char *dev, const char *property, const char *member, char *value, int len)
IUGetConfigText Opens configuration file and reads single text property.
int IUGetConfigSwitch(const char *dev, const char *property, const char *member, ISState *value)
IUGetConfigSwitch Opens configuration file and reads single switch property.
#define LOGF_INFO(fmt,...)
#define LOGF_DEBUG(fmt,...)
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...
#define LOGF_ERROR(fmt,...)
std::unique_ptr< ScopeDome > scopeDome(new ScopeDome())