Jump to content

Banner.jpg.b89429c566825f6ab32bcafbada449c9.jpg

Writing or Modifying INDI Drivers for Astro Imaging and Control with RPi


Gina

Recommended Posts

In the development of my rotating astro imaging rig using camera lenses, I have the requirement to control the camera rotation plus focussing and possibly zoom if I go for zoom lenses, in addition to image capture and mount control which is already covered in the INDI server and drivers for the Raspberry Pi.  ATM I'm doing this in the Arduino Nano and controlling it with Windows and control software written in Visual Basic.  This uses a Win 7 laptop in the observatory controlled remotely via TeamViewer.  I want to replace this with a Raspberry Pi and Linux.

I already have an all sky camera running INDI Server and controlled by KStars/Ekos on Linux Mint box indoors.  I'm using a standard INDI driver to control an RPi HAT and thence dew heaters.  The driver works but doesn't have a dedicated user interface so I would like to change this too.

I'm hoping I can get my head round modifying INDI drivers to suit my purposes and maybe write new drivers to extend control further.  I have experience of various programming languages including C++ and Python etc. though I may need to revise my Python as it's been a few years since I last used it.  I also have some knowledge of Linux.

I would appreciate help in pointing me in the right direction.  Thanks in advance :)

Link to comment
Share on other sites

  • Replies 59
  • Created
  • Last Reply

For the raspberry Pi GPIO side there's a few ways to do it. I went with the wiringPi library. See develop branch of https://bitbucket.org/BWGaryP/mup-astro-cat/src for more info on that + code. There's also some setup notes in the docs folder for getting wiringPi working without needing suid on the binary for gpio access; requires a env variable to be set.

Once you've done the tutorials in the INDI Driver Development docs, It's worth taking a look over a couple of the existing driver implementations. The documentation around properties felt a bit lacking to me but the source eventually makes things clearer.

I don't know that much about indi, only touched on the parts I needed to get a focuser going, but if you hit any issues with that ask away.

Link to comment
Share on other sites

As a MAC user I will be watching with interest as I was considering looking creating indi drivers for come of the gear I have as a Summer project - it's been 10yrs since I last set eyes on any code tho' :(

Link to comment
Share on other sites

  • 3 weeks later...

I was going to post in the software forum but remembered I'd posted about modifying INDI drivers before so searched for it and found this thread.  As what I'm thinking of involves my current hardware, I'll post here for now but will probably post a tutorial in the software forum when I've sorted things out a bit.

Currently I'm using the Astroberry Board driver to control camera cooling (a DIY Peltier TEC job) and two dew heaters for my all sky camera.  With the latest upgrade (new lens) I don't need cooling but it does need dew heaters and the Astroberry Board INDI driver is not ideal as far as the GUI in Ekos is concerned.

This is a screenshot of the Astroberry Board interface in the INDI Control Panel.  The relevant part is at the bottom - Line A, Line B, Line C and Line D.  The titles of these controls don't match what I'm doing with them!  The functions in the ASC are "Cooling"  ON/OFF,  "Dew Heater" ON/OFF and "Dry Raindrops" ON/OFF.  I don't know what System - Shutdown - Restart does and I don't really want controls that either do nothing (or worse do something unwanted).

Screenshot from 2017-02-06 13-18-01.png

I've already edited one source file in the Astroberry library to disable a couple of unwanted drivers in the set and I've looked at the rpi_brd.cpp file which includes the details of the user controls.  I reckon I could edit these before compiling and produce different labels.

Link to comment
Share on other sites

This is the relevant section of the code :-

    
    IUFillSwitch(&Switch0S[0], "SW0HALT", "Shutdown", ISS_OFF);
    IUFillSwitch(&Switch0S[1], "SW0REBOOT", "Restart", ISS_OFF);
    IUFillSwitchVector(&Switch0SP, Switch0S, 2, getDeviceName(), "SWITCH_0", "System", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);

    IUFillSwitch(&Switch1S[0], "SW1ON", "Power ON", ISS_OFF);
    IUFillSwitch(&Switch1S[1], "SW1OFF", "Power OFF", ISS_ON);
    IUFillSwitchVector(&Switch1SP, Switch1S, 2, getDeviceName(), "SWITCH_1", "Line A: 5V", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);

    IUFillSwitch(&Switch2S[0], "SW2ON", "Power ON", ISS_OFF);
    IUFillSwitch(&Switch2S[1], "SW2OFF", "Power OFF", ISS_ON);
    IUFillSwitchVector(&Switch2SP, Switch2S, 2, getDeviceName(), "SWITCH_2", "Line B: 5V", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);

    IUFillSwitch(&Switch3S[0], "SW3ON", "Power ON", ISS_OFF);
    IUFillSwitch(&Switch3S[1], "SW3OFF", "Power OFF", ISS_ON);
    IUFillSwitchVector(&Switch3SP, Switch3S, 2, getDeviceName(), "SWITCH_3", "Line C: 0-12V", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);

    IUFillSwitch(&Switch4S[0], "SW4ON", "Power ON", ISS_OFF);
    IUFillSwitch(&Switch4S[1], "SW4OFF", "Power OFF", ISS_ON);
    IUFillSwitchVector(&Switch4SP, Switch4S, 2, getDeviceName(), "SWITCH_4", "Line D: 12V", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);

I think it would show what I want if I changed it to this :-

    
    IUFillSwitch(&Switch0S[0], "SW0HALT", "Shutdown", ISS_OFF);
    IUFillSwitch(&Switch0S[1], "SW0REBOOT", "Restart", ISS_OFF);
    IUFillSwitchVector(&Switch0SP, Switch0S, 2, getDeviceName(), "SWITCH_0", "System", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);

    IUFillSwitch(&Switch1S[0], "SW1ON", "ON", ISS_OFF);
    IUFillSwitch(&Switch1S[1], "SW1OFF", "OFF", ISS_ON);
    IUFillSwitchVector(&Switch1SP, Switch1S, 2, getDeviceName(), "SWITCH_1", "Cooling", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);

    IUFillSwitch(&Switch2S[0], "SW2ON", "ON", ISS_OFF);
    IUFillSwitch(&Switch2S[1], "SW2OFF", "OFF", ISS_ON);
    IUFillSwitchVector(&Switch2SP, Switch2S, 2, getDeviceName(), "SWITCH_2", "Dew Heater", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);

    IUFillSwitch(&Switch3S[0], "SW3ON", "ON", ISS_OFF);
    IUFillSwitch(&Switch3S[1], "SW3OFF", "OFF", ISS_ON);
    IUFillSwitchVector(&Switch3SP, Switch3S, 2, getDeviceName(), "SWITCH_3", "Dry Raindrops", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);

    IUFillSwitch(&Switch4S[0], "SW4ON", "Power ON", ISS_OFF);
    IUFillSwitch(&Switch4S[1], "SW4OFF", "Power OFF", ISS_ON);
    IUFillSwitchVector(&Switch4SP, Switch4S, 2, getDeviceName(), "SWITCH_4", "Spare", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);

 

Link to comment
Share on other sites

If you want to hide the shutdown property, one option is to use the updateProperties() method. This is from what I could gather, how you're supposed to display properties only when they can be used. So for example, when connected, everything can show, when disconnected, some properties don't make sense so you can remove them until connected.

For the shutdown property you should be able to skip the isConnected test and just always deleteProperty(Switch0SP.name);

Although you could also just not create the property in initProperties, if it's created in your driver as opposed to higher up that you've inherited from. In the latter case delete should work, but you'd have to check the higher up classes just to be sure they're only reacting to the property and not directly using it, since it will be deleted.

Link to comment
Share on other sites

Back now to the original purpose of this thread viz. controlling the camera rotation in my widefield imaging rig.

Whilst the Astroberry Focuser INDI driver has many of the controls I would like to use in the GUI it's probably inherited from the Focuser class.  Checking the rpi_focus.h file this is indeed the case so as this isn't a focuser we don't want inherited focuser functionality.   Can probably copy some of the code for the controls from it though.  OTOH checking the Astroberry Board code shows it only inherits the DefaultDevice class.

 

Link to comment
Share on other sites

Before starting to write a driver by combining parts from other driver code I need to decide which controls I want.  Since I'm not modifying a single INDI driver I can start from scratch.  The rotation drive moves the camera 180 degrees and with virtually anything possible I guess it makes sense to simply enter the angle in degrees in a text box.  This would be associated with a Set control button, maybe a progress count and a light to show when completed.  Plus a Label saying "Camera Angle".  And of course, "Connect" etc.

In the code the degrees number would be converted to steps and the difference from the current step count calculated.  The code would then issue direction and step count to a routine that would send logic state to the DIR and pulses to the STEP control.  Code from the focuser driver might be used for the driver control or I could write my own code.

 

Link to comment
Share on other sites

Looking at the ratio of degrees to steps, the gear ratio is 10:1 and NEMA17 stepper motors have a full step resolution of 200 steps per revolution so 2000 steps would turn the cage by 360°.  Since the cage wants to turn 180° to cover required angles, this corresponds to 1000 steps.  5.55r steps per degree.  That's awkward!  Needs careful coding to prevent errors when reversing.  An error of 1 step wouldn't matter but if there were cumulative errors is would matter after a while.

I think I should have looked further ahead when I designed the gear drive but hindsight is a wonderful thing :D Guess I could add another large gear onto the present setup - the pinion is no problem.  A gear ratio of 90:10 = 9:1 and 200 steps per revolution would correspond to 360°/9 = 40° so 1° - 200/40 = 5 steps - ideal :)

Link to comment
Share on other sites

That wasn't practical so I've gone for 9:1 and 5 steps per degree.  I have a modified version of the Astroberry Focuser working to control the rotation but there are a number of unwanted controls in the GUI and I want to get rid of those.  The GUI is inherited from further up the class structure so not able to be changed much in the rotator.cpp source file.  Hence I'm going to study writing my own drivers from scratch.

I plan to go through the tutorials on driver writing and see what I can learn.  However, I have another tack to try and that's Python which I've used in the past for my weather station amongst other things.  Whether this works better than directly programming in C++ remains to be seen but I'm thinking this may increase the scope of uses, particularly interfacing to the "real world".

I have bought two books about the Raspberry Pi one of which is exclusively interfacing matters. These are

Raspberry Pi User Guide

Exploring Raspberry Pi: Interfacing to the Real World with Embedded Linux

These both cover Python programming and there's a tutorial on using Python with INDI so I figure this must be worth investigating.  INDI Python Programming on Raspberry PI

Link to comment
Share on other sites

Just tried again to register with the INDI forum without success :(  Fill in page 1, fill in page 2, but from there it goes to a format-less page where it seems to want the same info again.  Anyone here have any ideas of what I can do, please?

Link to comment
Share on other sites

No?  Oh well, I'll just carry on without posting access to the INDI forum...

The tutorials seem to want testing in the RPi with monitor etc. connected.  That would require a considerable reorganisation of my hardware setup :( The advanced RPi programming book I've got shows how to cross-compile RPi software on a Linux desktop, so I'll look into that later.  Meanwhile, thinking about it, it might be worthwhile taking my HDMI monitor, keyboard and trackball off the Win 7 desktop and using them with an RPi.  Would save taking the SD card out of the RPi to edit in the reader on the Linux desktop.

Link to comment
Share on other sites

Been looking into the tutorials and only the first has any explanation that I can find.  The others just describe how to take the source code and compile it without the explanation I would like.  I'm going to have to do more searching plus studying the code and maybe trying some experiments.  This isn't as straightforward as it ought to be!  That might mean though that if I can fathom it out I might be able to produce a tutorial that we lesser mortals can understand.

I need to find out where the various GUI code is located so that I can assemble the appropriate controls to make the GUI as I want to see it.  I think (and hope) this is proper Object Orientated Programming like I used to be familiar with though that was a while ago and recent programming has been somewhat "loose" in comparison.  I would rather like to get back into "proper programming" again.

Link to comment
Share on other sites

I'm going to check this out on my Linux Mint desktop to the point of having the source code available to examine then see what I can make of it.

Firstly we need to install subversion so that we can ckeckout the INDI source code.

sudo apt-get install subversion cmake libgps-dev

Then download the INDI library source code.

svn checkout svn://svn.code.sf.net/p/indi/code/trunk/libindi

We should now have the source code in ~/libindi

gina@Mint-Desktop ~ $ cd libindi
gina@Mint-Desktop ~/libindi $ ls
AUTHORS   base64.h   CMakeLists.txt  config.h.cmake  COPYING.GPL   COPYRIGHT  drivers      eventloop.c  examples  fq.h       indidevapi.h  indidriver.h      indiserver.c  libindi.pc.cmake  LICENSE  README  tools
base64.c  ChangeLog  cmake_modules   COPYING.BSD     COPYING.LGPL  Doxyfile   drivers.xml  eventloop.h  fq.c      indiapi.h  indidriver.c  indidrivermain.c  INSTALL       libs              NEWS     TODO

drivers, examples, tools, cmake modules and lib are directories.

Now to see what is there ...

Link to comment
Share on other sites

This is going to take a while :D   One thing of interest I've found (not listed in the INDI Devices) is "Roll-Off" in the "Domes" group.  This looks like just what I want to control my roll off roof :)  I was surprised not to see a roll off roof INDI driver listed in the main documentation - evidently added since :)

Link to comment
Share on other sites

Been looking through more files and accumulating information.  I think I may be able to run many tests on my Linux Mint desktop without a Raspberry Pi.  Obviously I can't test the hardware such as GPIO without the right hardware but for developing the driver controls and testing the GUI, I think it might work.  This would save a lot of messing about.  Anyway, I'm going to try it.

Link to comment
Share on other sites

Fell at the first fence :)

gina@Mint-Desktop ~ $ cd libindi
gina@Mint-Desktop ~/libindi $ cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug .
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is unknown
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- broken
CMake Error at /usr/share/cmake-3.5/Modules/CMakeTestCCompiler.cmake:61 (message):
  The C compiler "/usr/bin/cc" is not able to compile a simple test program.

  It fails with the following output:

   Change Dir: /home/gina/libindi/CMakeFiles/CMakeTmp

Following these commands from the INDI tutorial

svn checkout svn://svn.code.sf.net/p/indi/code/trunk/libindi
cd libindi
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug .
sudo make install

Had already done the first two and been reading the files created.  Seems to be something wrong with the C++ compiler.

I'll try sudo apt-get update && sudo apt-get upgrade && sudo reboot

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. By using this site, you agree to our Terms of Use.