×

INDI Library v2.0.6 is Released (02 Feb 2024)

Bi-monthly release with minor bug fixes and improvements

Moonlite focuser protocol

  • Posts: 11
  • Thank you received: 0
The reason it works without the capacitor is because the INDI driver is not interrogating the Moonlite controller on startup.

The ASCOM driver, once you connect, it immediately interrogates the controller, and if it doesn't immediately receive a response it does not detect the controller.

However the stand-alone app (and presumably the INDI driver) merely opens the connection and then starts merrily sending Moonlite commands. So long as the commands come in >2 seconds after connection (to give the Arduino a chance to reset) then all is well... :)
9 years 10 months ago #1087

Please Log in or Create an account to join the conversation.

  • Posts: 21
  • Thank you received: 1

Replied by Cees on topic Moonlite focuser protocol

I have made some more modifications. (Hope you are ok with this orly_andico ?).
The issue I saw was that the focus module would start capturing a new image when the focuser was still moving. Also, the inward move did not always report the correct position. Turns out there is a small bug in the original :GI# response.
stepper.distanceToGo() according to the AccelStepper "the distance from the current position to the target position in steps. Positive is clockwise from the current position" Therefor, in the original code any inward movement followed by a :GI# request would get a "I'm not moving" response when distanceToGo() < 0 and that is incorrect.
I have also modified the loop it bit and use the enablePin rather than the sleep pin although I haven't been able to try this other than simulation. (Still raining)

Any comments and or suggestions are welcome.

Can't figure out how to add an attachment to the post so here is the code
// Moonlite-compatible stepper controller
//
// Uses AccelStepper (http://www.airspayce.com/mikem/arduino/AccelStepper/)
//
// Inspired by (http://orlygoingthirty.blogspot.co.nz/2014/04/arduino-based-motor-focuser-controller.html)
// orly.andico@gmail.com, 13 April 2014
//
// Modified for indilib, easydriver by Cees Lensink
 
 
#include <AccelStepper.h>
 
int stepperPin = 2;
int dirPin = 3;
int powerPin = 4;
boolean useSleep = true; // true= use sleep pin, false = use enable pin
int ledPin = 13;
 
// maximum speed is 160pps which should be OK for most
// tin can steppers
#define MAXSPEED 160
#define SPEEDMULT 3
 
AccelStepper stepper(1, stepperPin, dirPin);
 
#define MAXCOMMAND 8
 
char inChar;
char cmd[MAXCOMMAND];
char param[MAXCOMMAND];
char line[MAXCOMMAND];
long pos;
int eoc = 0;
int idx = 0;
boolean isRunning = false;
 
char tempString[10];
 
 
void setup()
{  
  Serial.begin(9600);
  pinMode(powerPin,OUTPUT);
  // we ignore the Moonlite speed setting because Accelstepper implements
  // ramping, making variable speeds un-necessary
  stepper.setSpeed(MAXSPEED);
  stepper.setMaxSpeed(MAXSPEED);
  stepper.setAcceleration(50);
  turnOff();
  memset(line, 0, MAXCOMMAND);
}
 
 
//
 
//
 
 
void loop(){
  if (isRunning) { // only have to do this is stepper is on
    stepper.run();
    if (stepper.distanceToGo() == 0) {
      //  we have arrived, remove power from motor
      turnOff();
    }
  }
 
  // read the command until the terminating # character
  while (Serial.available() && !eoc) {
    inChar = Serial.read();
    if (inChar != '#' && inChar != ':') {
      line[idx++] = inChar;
      if (idx >= MAXCOMMAND) {
        idx = MAXCOMMAND - 1;
      }
    } 
    else {
      if (inChar == '#') {
        eoc = 1;
      }
    }
  } // end while Serial.available()
  // we may not have a complete command yet but there is no character coming in for now and might as well loop in case stepper needs updating
  // eoc will flag if a full command is there to act upon
 
  // process the command we got
  if (eoc) {
    memset(cmd, 0, MAXCOMMAND);
    memset(param, 0, MAXCOMMAND);
 
    int len = strlen(line);
    if (len >= 2) {
      strncpy(cmd, line, 2);
    }
 
    if (len > 2) {
      strncpy(param, line + 2, len - 2);
    }
 
    memset(line, 0, MAXCOMMAND);
    eoc = 0;
    idx = 0;
 
    //now execute the command 
 
    //Immediately stop any focus motor movement. returns nothing
    //code from Quickstop example. This is blocking
    if (!strcasecmp(cmd, "FQ")) {
      turnOn();
      stepper.stop(); // Stop as fast as possible: sets new target
      stepper.runToPosition(); 
      // Now stopped after quickstop
    }
 
    //Go to the new position as set by the ":SNYYYY#" command. returns nothing    // initiate a move
    //turn stepper on and flag it is running
    // is this the only command that should actually make the stepper run ?
    if (!strcasecmp(cmd, "FG")) {
      turnOn();
    }
 
    //Returns the temperature coefficient where XX is a two-digit signed (2’s complement) hex number.
    //hardcoded
    if (!strcasecmp(cmd, "GC")) {
      Serial.print("02#");      
    }
 
    //Returns the current stepping delay where XX is a two-digit unsigned hex number. See the :SD# command for a list of possible return values.
    //hardcoded for now
    // might turn this into AccelStepper acceleration at some point
    if (!strcasecmp(cmd, "GD")) {
      Serial.print("02#");      
    }
 
    //Returns "FF#" if the focus motor is half-stepped otherwise return "00#"
    //hardcoded
    if (!strcasecmp(cmd, "GH")) {
      Serial.print("00#");
    }
 
    //Returns "00#" if the focus motor is not moving, otherwise return "01#",
    //AccelStepper returns Positive as clockwise
    if (!strcasecmp(cmd, "GI")) {
      if (stepper.distanceToGo() == 0) {
        Serial.print("00#");
      } 
      else {
        Serial.print("01#");
      }
    }
 
    //Returns the new position previously set by a ":SNYYYY" command where YYYY is a four-digit unsigned hex number.
    if (!strcasecmp(cmd, "GN")) {
      pos = stepper.targetPosition();
      sprintf(tempString, "%04X", pos);
      Serial.print(tempString);
      Serial.print("#");
    }
 
    //Returns the current position where YYYY is a four-digit unsigned hex number.
    if (!strcasecmp(cmd, "GP")) {
      pos = stepper.currentPosition();
      sprintf(tempString, "%04X", pos);
      Serial.print(tempString);
      Serial.print("#");
    }
 
    //Returns the current temperature where YYYY is a four-digit signed (2’s complement) hex number.
    if (!strcasecmp(cmd, "GT")) {
      Serial.print("0020#");
    }
 
    //Get the version of the firmware as a two-digit decimal number where the first digit is the major version number, and the second digit is the minor version number.
    //hardcoded
    if (!strcasecmp(cmd, "GV")) {
      Serial.print("10#");
    }
 
    //Set the new temperature coefficient where XX is a two-digit, signed (2’s complement) hex number.
    if (!strcasecmp(cmd, "SC")) {
      //do nothing yet
    }
 
    //Set the new stepping delay where XX is a two-digit,unsigned hex number.
    if (!strcasecmp(cmd, "SD")) {
      //do nothing yet
    }
 
    //Set full-step mode.
    if (!strcasecmp(cmd, "SF")) {
      //do nothing yet
    }
 
    //Set half-step mode.
    if (!strcasecmp(cmd, "SH")) {
      //do nothing yet
    }
 
    //Set the new position where YYYY is a four-digit
    if (!strcasecmp(cmd, "SN")) {
      pos = hexstr2long(param);
      // stepper.enableOutputs(); // turn the motor on here ??
      turnOn();
      stepper.moveTo(pos);
    }
 
    //Set the current position where YYYY is a four-digit unsigned hex number.
    if (!strcasecmp(cmd, "SP")) {
      pos = hexstr2long(param);
      stepper.setCurrentPosition(pos);
    }
 
  }// end if(eoc)
 
 
} // end loop
 
long hexstr2long(char *line) {
  long ret = 0;
 
  ret = strtol(line, NULL, 16);
  return (ret);
}
 
void turnOn() {
  if (useSleep) {
    digitalWrite(powerPin, HIGH);
  } else {
    digitalWrite(powerPin, LOW);
  }
  digitalWrite(ledPin, HIGH);
  isRunning = true;
}
void turnOff() {
  if (useSleep) {
    digitalWrite(powerPin, LOW);
  } else {
    digitalWrite(powerPin, HIGH);
  }
  digitalWrite(ledPin, LOW);
  isRunning = false; 
}
 
Last edit: 9 years 10 months ago by Cees. Reason: code update
9 years 10 months ago #1098

Please Log in or Create an account to join the conversation.

  • Posts: 11
  • Thank you received: 0
Sounds good. I've set up a google code repository for this and my other astro hacks.

code.google.com/p/astrohacks/source/brow...2Ftrunk%2Fastrohacks

if you have a google account (who doesn't) and want to be added just ping me. it's better if there's one central location rather than "source control by email"

Interestingly the stock Windows client for Moonlite worked just fine even with the buggy :GI# implementation hence I never seem to have hit this issue. My "fix" is a bit different..
Last edit: 9 years 10 months ago by Orlando Andico.
9 years 10 months ago #1100

Please Log in or Create an account to join the conversation.

  • Posts: 85
  • Thank you received: 3
Hi, good to know that the sketch is beeing worked on.
I have a quick question, what is the difference between the sleepPin and enablePin? I currently only have sleepPin connected to my easy driver board and to connect enablePin will require some soldering.

Oh another thing I noticed was (this is using your first version of the sketch, I haven't tried the latest) that when I set the step size to small values (like <50 ticks) the stepper first made a small move in the wrong direction, and if the step size was small enough it didn't move back in the right direction after that initial wrong direction step.
9 years 10 months ago #1101

Please Log in or Create an account to join the conversation.

  • Posts: 21
  • Thank you received: 1

Replied by Cees on topic Moonlite focuser protocol

danielfranzen:
It is my understanding that the sleep pin turns the whole board off including power to the motor and the enable pin only switches the power to the motor. If you do not connect them the whole thing should still run.

My new version of the code didn't work when I connected it to the board. Turns out that the enablePin needs to be inverted for AccelStepper as in HIGH means off and LOW means on. Easy to do with a stepper.setPinsInverted( false, false, true); in setup
I have edited the code in the previous post to reflect this change and some other minor changes. I'm still not convinced this is actually working correct because the easydriver board still maintains power to the motor when it shouldn't as far as I can tell. I'll keep tinkering.

I have not noticed the problems with the small steps. Or perhaps I have? I sometimes noticed that the reported position is not always the actual position. I suspect this is a indi driver artifact. E.g start at 2000. Move 50 out. At completion it would report position 2049. Move 50 in. Reported position would than go 2049->2050->2049->2048 etc etc
I suspect that the indi driver gets a "not moving" when the arduino is at 2050 and the driver is still at 2049 . Because it is "not moving" ithe driver doesn't update to the actual position.
I'm going to make a version where I can snoop on the arduino with another serial port and see whther the indi driver and arduino are in sync or not


orly_andico:
I have taken your initial code as an opportunity to learn more about arduino and indilib. I only just getting my feet wet with this.
I'll check out the code.google.com thing and let you know.
fwiw, the version I use doesn't seem to work with the Windows Client for Moonlite. Go figure
Perhasp one day we'll have a version that works for all.
9 years 10 months ago #1105

Please Log in or Create an account to join the conversation.

  • Posts: 21
  • Thank you received: 1

Replied by Cees on topic Moonlite focuser protocol

Ok. This is the last time I will do it this way. Next time I have an update it will be at some file download place.
I have edited the version in the previous post. It seems to work with the either the sleep or the enable pin.
At the top somewhere you choose which one you use. If you do not use either it will still work but it will keep the motor powered up all the time.
9 years 10 months ago #1106

Please Log in or Create an account to join the conversation.

  • Posts: 21
  • Thank you received: 1

Replied by Cees on topic Moonlite focuser protocol

fwiw, wrt the discrepancy of the actual vs displayed position the following. I have been "snooping" on the communication between the indidriver and the arduino communication using the arduino softSerial on another serial port. The arduino is reporting the correct position to the driver but this is not always displayed correctly in the indi control panel. It is sometimes off by a small (1 in my case) number.
For example.
move to absolute 2000 - I see :GP#07d0# position reported 2000 in control panel
move relative out 40 - position reported 2040
move relative in 40 - position reported 2001 yet :GP#07d0# which is 2000

the above doesn't always happen.
I don't think it matters too much because the driver and the arduino now where it is at.

Does this happen with an actual moonlite focuser as well ?
9 years 10 months ago #1116

Please Log in or Create an account to join the conversation.

  • Posts: 85
  • Thank you received: 3
Hello.

I have tested your latest version and it works with my setup (no enable pin just sleep pin).

I have also found out that the small stutter that my stepper had happened when you powered it on back after it was in sleep mode. I disabled power on/off to test and when the power was always on, no strange movements were noticed.

So I modified the code a little bit to only put it in sleep mode if the stepper not have been moved for 30 seconds. That makes it possible to adjust focus without powering the board on and off with every correction.
I don't know if it only is my setup that have this behavior but maybe it can be useful to others as well.

I've attached my modified code if anybody want to look at/use it.
Edit: Could not attach file either.
Here is a dropbox link instead:
dl.dropboxusercontent.com/u/8802413/Moon...nz_30sSleepDelay.ino



Regards
Daniel
Last edit: 9 years 10 months ago by Daniel Franzén. Reason: Couldn't attach file
9 years 10 months ago #1128

Please Log in or Create an account to join the conversation.

  • Posts: 21
  • Thank you received: 1

Replied by Cees on topic Moonlite focuser protocol

Excellent. I was thinking along the same lines about adding a delay sleep timer.
9 years 10 months ago #1129

Please Log in or Create an account to join the conversation.

  • Posts: 85
  • Thank you received: 3
Hello again.

I've mounted my stepper to my focuser and everything works fine. However the moonlite driver has a max limit of 30000 steps and with my setup 30000 steps only manages to move my focuser about half way out. Is there a way to modify the limits? There is an option that says maximum travel, but that doesn't seem to do anything.

/Daniel
9 years 10 months ago #1197

Please Log in or Create an account to join the conversation.

The 30000 limit is for relative focusing, but the absolute should be 60000, it is updated now.
9 years 10 months ago #1202

Please Log in or Create an account to join the conversation.

  • Posts: 85
  • Thank you received: 3
Hello knro.

Thanks for updating the driver. I've tested it and now you can select to move the focuser 60000 ticks in total.
However I think there is an int overflow issue when the focuser reports its position as it starts to show negative values when it passes > 32000 (32767 most likely).

You can see it in the video I've made.


It also appears that this (I assume) causes some unwanted behavior because when I went from 0 to 60000 and back to 0, the focuser hit bottom before stopping and I had to abort the movement. I think It reported it was at something like 5000 when the focuser actually was at 0 (in the bottom).
This could however be a problem with the arduino code, I don't know...

/Daniel
9 years 10 months ago #1207

Please Log in or Create an account to join the conversation.

Time to create page: 0.811 seconds