×

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

Bi-monthly release with minor bug fixes and improvements

I need help to connect the pyxis driver to my arduino code !!

  • Posts: 250
  • Thank you received: 3
well, I can't put it as an attachment, so
I put you the code
#include <AccelStepper.h>     // https://www.pjrc.com/teensy/td_libs_AccelStepper.html
 
#define EnablePin 12
#define IN1 4 
#define IN2 5 
#define IN3 6 
#define IN4 7 
#define MotorInterfaceType 4
 
#include <EEPROM.h>
 
// EEPROM addresses
#define FOCUSER_POS_START 0
#define STEPPER_SPEED_ADD 3
 
AccelStepper stepper(MotorInterfaceType, IN1, IN2, IN3, IN4);
 
// Global vars
boolean moving = false;
boolean hold = false;
boolean reversed;
boolean positionSaved;               // Flag indicates if stepper position was saved as new focuser position
boolean firstPrint = false;
boolean homeFound = true;
String inputString;                  // Serial input command string (terminated with \n)
boolean findingHome = false;
 
// *************  this value must be changed for each specific setup ***************************************
long maxSteps = 505960;  // **** steps needed for 2 complete revolutions.  prevent cord wrap.
long minStep = 0;
//  Must also enter this value/720 = steps/degree for first time ASCOM driver setup, click "properties
// ******************************************************************************************************
 
int manualMoveStepSize = 50;  //higher number for faster manual moves
int findHomeStepSize = 100; //adjusts finding home speed
 
int buttonStateCW = HIGH;
int buttonStateCCW = HIGH;
boolean manualMoveCW = false;
boolean manualMoveCCW = false;
 
int HEState = 0;
long lastDebounceTime = 0;
long debounceDelay = 20;
 
void setup()
{
  // Initialize serial
  Serial.begin(57600);
  pinMode(EnablePin, OUTPUT);
  analogWrite(EnablePin, 0);
 
  // Initialize stepper motor
  stepper.setMaxSpeed(200);// 5000 works good,  use 500000 for confrom test1000 geared rotator10000 for geared stepper   200 for non-geared large stepper(500 max)  also may depend on what else is on loop()
  stepper.setAcceleration(1000);//1000 for geared rotator  10000 for geared stepper    1000 for non-geared large stepper
  //stepper.setCurrentPosition(readFocuserPos());
  stepper.setCurrentPosition(0);
  positionSaved = true;
  inputString = "";
  reverseDir(false);
}
 
void loop()
{
  if (findingHome == true) {
    findHome();
  }
 
  // Stepper loop
  if (stepper.distanceToGo() == 0) {
    if (hold == false) {
      analogWrite(EnablePin, HIGH);
    }
  } else {
    analogWrite(EnablePin, 200);
  }
  if (stepper.distanceToGo() == 0 && !positionSaved) {
    saveFocuserPos(stepper.currentPosition());
    positionSaved = true;
  }
  if (stepper.distanceToGo() != 0 && !firstPrint) {
    firstPrint = true;
  }
 
  if (stepper.distanceToGo() != 0) {
    moving = true;
  } else {
    moving = false;
  }
  stepper.run();
}
 
// Interrupt serial event
void reverseDir(boolean rev) {
  stepper.setPinsInverted(rev, false, false);  //for FSQ85(true, false, false) ---  for TSA 120should be (false, false, false)  (dir, step, enable)
  //not reversed is std setup for tsa-120
  reversed = rev;
}
void Hold(boolean conthold) {
  hold = conthold;
}
 
void serialEvent() {
  while (Serial.available() > 0) {
    char inChar = (char)Serial.read();
    if (inChar == ':' || inChar == '#') {
      if (inputString == "PV") inputString = "V"; // Version
      if (inputString == "GA") inputString = "B"; // bit 1 for switch 2
      if (inputString == "SH") inputString = "H"; // Starts the Find Home routine
      if (inputString == "GS") inputString = "Z"; // bit 2 for In limit switch
      if (inputString == "GT") inputString = "D"; // Sensor temperature in tenths of a degree, ex: 25°C = 250d
      if (inputString == "GV") inputString = "E"; // System voltage in tenths of a volt, ex 12.0V = 120d
      if (inputString == "PD") inputString = "D"; // Set the display brightness
      if (inputString == "PL") inputString = "D"; // Set the display sleep brightness
      if (inputString == "PF") inputString = "F"; // Gets the current focuser type. Ex: "2.5 NC#"
      if (inputString == "PS") inputString = "X"; // Gets the current focuser serial number
      if (inputString == "PU") inputString = "W"; // Gets a user defined field
      if (inputString == "PE") inputString = "C"; // Enables or disables the encoders
      if (inputString == "PR") inputString = "J"; // Issues a reset
      if (inputString == "Pt") inputString = "D"; // Adjusts the temperature offset
      if (inputString == "Pu") inputString = "Y"; // Sets the user text field
      serialCommand(inputString);
      inputString = "";
    }
    else {
      inputString += inChar;
    }
  }
}
 
void serialCommand(String command) {
  String param = command.substring(4);
  String comando = command.substring(0, 3); //:2SN 12345678#
  if (comando == "2GP") command = "G"; // Current position count, 8 digits, signed, 0 padding
  if (comando == "1GP") command = "K"; // DUMMY Current position
  if (comando == "3GP") command = "K"; // DUMMY Current position
  if (comando == "2GM") command = "Q"; // IS MOVING
  if (comando == "2GN") command = "A"; // New (or Target) position count, 8 digits, signed, 0 padding
  if (comando == "2GR") command = "A"; // Motor step delay in 100 microsecond intervals
  if (comando == "2SQ") command = "S"; // Stops motor
  if (comando == "2SM") command = "A"; // Starts motor to move to the “NEW” focus position
  if (comando == "2SP") command = "P"; // Set the current position, 32 bit value, signed
  if (comando == "2SN") command = "M"; // Move to the New position count, 32 bit value, signed
  if (comando == "1SR") command = "A"; // Set the motor step rate in 100 microsecond intervals.
  if (comando == "2SR") command = "A"; // Set the motor step rate in 100 microsecond intervals.
  if (comando == "3SR") command = "A"; // Set the motor step rate in 100 microsecond intervals.
 
  //Serial.println(command);
 
  switch (command.charAt(0)) {
    case 'Q':
      if (moving == true) {
        Serial.println("01#");
      } else {
        Serial.println("00#");
      }
    case 'Y':
      Serial.println("RC 8#");
      break;
    case 'K':
      Serial.println("30000#");
      break;
    case 'A':
      Serial.println("#");
      break;
    case 'B':
      Serial.println("00#");
      break;
    case 'Z':
      Serial.println("00#");
      break;
    case 'D':
      Serial.println("105#");
      break;
    case 'E':
      Serial.println("123#");
      break;
    case 'F':
      Serial.println("3.5 NC#");
      break;
    case 'X':
      Serial.println("20200516#");
      break;
    case 'W':
      Serial.println("StarPI Rotator#");
      break;
    case 'G':
      printCurrentPosition();
      break;
    case 'P':
      saveCurrentPos(stringToLong(param));
      break;
    case 'H':    // find home
      if (param = 2) findHome();
      break;
    case 'M':
      moveStepper(stringToLong(param), false);
      break;
    case 'S':
      halt();
      break;
    case 'R':
      int value;
      value = (stringToNumber(param));
      if (value == 0) {
        reverseDir(false);
      } else {
        reverseDir(true);
      }
      break;
    case 'C':// continuos hold
      int value2;
      value2 = (stringToNumber(param));
      if (value2 == 0) {
        Hold(false);
      } else {
        Hold(true);
      }
      Serial.println("#");
      break;
    case 'V':
      Serial.println("1.3#");
      break;
    case 'J': // Reset Arduino myFocuserPro2 controller
      software_Reboot();
      break;
  }
}
 
void printCurrentPosition() {
  Serial.print("00");
  if (stepper.currentPosition() < 100000) Serial.print("0");
  if (stepper.currentPosition() < 10000) Serial.print("0");
  if (stepper.currentPosition() < 1000) Serial.print("0");
  if (stepper.currentPosition() < 100) Serial.print("0");
  if (stepper.currentPosition() < 10) Serial.print("0");
  Serial.print(stepper.currentPosition());
  Serial.println("#");
}
 
void moveStepper(long newPos, boolean manualMove) {
  Serial.println("#");
  if (findingHome == true) {
    stepper.moveTo(newPos);
  return;
  }
 
  if (newPos != stepper.currentPosition()) {
    if (newPos < minStep || newPos > maxSteps) {
      return;
    } else {
      stepper.moveTo(newPos);
      positionSaved = false;
      firstPrint = false;
    }
  }
}
 
void halt() {
  Serial.println("#");
  stepper.stop();
}
 
void saveCurrentPos(long newPos) {
  Serial.println("#");
  if (newPos < minStep) newPos = minStep;
  stepper.setCurrentPosition(newPos);
  moveStepper(newPos, false);
  saveFocuserPos(newPos);
  positionSaved = true;
}
 
void findHome() {
  Serial.println("#");
  long newPos = maxSteps / 4;
  homeFound = true;
  findingHome = false;
  saveCurrentPos(newPos);
}
// reboot the Arduino
void software_Reboot() {
  // jump to the start of the program
  asm volatile ( "jmp 0");
}
 
void saveFocuserPos(long newPos) {
  writeLong(getSaveFocuserPosAddress() + 1, newPos);
}
 
long readFocuserPos() {
  return readLong(getReadFocuserPosAddress() + 1);
}
 
void writeWord(word address, word value) {
  EEPROM.update(address, lowByte(value));
  EEPROM.update(address + 1, highByte(value));
}
 
word readWord(word address) {
  return word(EEPROM.read(address + 1), EEPROM.read(address));
}
 
long readLong(word address) {
  word lowWord = readWord(address);
  word highWord = readWord(address + 2);
  return lowWord + highWord * 65536;
}
 
void writeLong(word address, long value) {
  word lowWord = value % 65536;
  word highWord = value / 65536;
  writeWord(address, lowWord);
  writeWord(address + 2, highWord);
}
 
int stringToNumber(String thisString) {
  int i, value = 0, length;
  length = thisString.length();
  for (i = 0; i < length; i++) {
    value = (10 * value) + thisString.charAt(i) - (int) '0';
  }
  return value;
}
 
long stringToLong(String thisString) {
  boolean neg = false;
  if (thisString.indexOf("-") == 0) {
    thisString = thisString.substring(1);
    neg = true;
  }
  //Serial.println(thisString);
  long value = 0;
  int i, length;
  length = thisString.length();
  for (i = 0; i < length; i++) {
    value = (10 * value) + thisString.charAt(i) - (int) '0';
  }
  if (neg == true) {
    value = maxSteps - value;
  }
  return value;
}
 
// Simple EEPROM wear leveling
int getSaveFocuserPosAddress() {
  for (byte x = 0; x < 20; x++) {
    int address = FOCUSER_POS_START + 5 * x;
    if (EEPROM.read(address) == 0) {
      EEPROM.update(address, 0xFF);
      return address;
    }
  }
  // Array is full, erase it and start from 0 - takes about 100ms
  for (byte x = 0; x < 20; x++) {
    EEPROM.update(FOCUSER_POS_START + 5 * x, 0);
    EEPROM.update(FOCUSER_POS_START, 0xFF);
    return FOCUSER_POS_START;
  }
}
 
int getReadFocuserPosAddress() {
  for (byte x = 0; x < 20; x++) {
    int address = FOCUSER_POS_START + 5 * x;
    if (EEPROM.read(address) == 0) {
      return FOCUSER_POS_START + 5 * (x - 1);
    }
  }
}
2 years 5 months ago #76579

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

  • Posts: 250
  • Thank you received: 3
Well, I guess I'm not having much luck right now.
I'm waiting for someone to explain to me or to tell me that it's not possible either to modify the display of the driver in kstars or to know the commands and the returns that the driver sends.

see you soon
Christophe
2 years 5 months ago #76607

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

You can checkout the Nightcrawler driver source code and the implementation of the findHome function.

What is it you're trying to do exactly if I may ask? Using Arduino to make a Nightcrawler compatible rotator?
2 years 5 months ago #76617

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

  • Posts: 250
  • Thank you received: 3
Hello
So, indeed I would like to adapt an arduino code for this driver.
I already have the one for the driver, but it is too complicated because it is also for a focuser, so I would like to try to make a simpler one.

And my second question is to know if there is a way to modify the nightcrawler driver to make a simpler one, just for a rotator.

Like for example:
I would just need in the configurations, the "HOME" with the position that we want (from 0 to 360 °) to choose.
And to be able to do it either by pressing a button, or, automatically at the beginning of its use.

I don't know if it's possible

See you soon
Christophe
2 years 5 months ago #76623

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

Just copy over the nightcrawler.h & cpp files and edit them accordingly to remove the unnecessary bits. Of course, you need to have some understand of INDI code, but it's mostly straight forward.
2 years 5 months ago #76630

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

  • Posts: 250
  • Thank you received: 3
Last edit: 2 years 5 months ago by Porchet.
2 years 5 months ago #76636

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

  • Posts: 250
  • Thank you received: 3
Hello Jasem
then this is my problem, I'm really not expert in indi code, but if I look at the nightcrawler.h code there is a lot of parts I could remove, I think, that have nothing to do with the rotator, like ...

// Focus Sync
IUFillNumber(&SyncFocusN[0], "FOCUS_SYNC_OFFSET", "Ticks", "%.f", 0, 100000., 0., 0.);
IUFillNumberVector(&SyncFocusNP, SyncFocusN, 1, getDeviceName(), "FOCUS_SYNC", "Sync", MAIN_CONTROL_TAB, IP_RW, 0,
IPS_IDLE );

// Voltage
IUFillNumber(&VoltageN[0], "VALUE", "Value (v)", "%.2f", 0, 30., 1., 0.);
IUFillNumberVector(&VoltageNP, VoltageN, 1, getDeviceName(), "Voltage", "Voltage", MAIN_CONTROL_TAB, IP_RO, 0, IPS_IDLE );

// Temperature
IUFillNumber(&TemperatureN[0], "TEMPERATURE", "Value (C)", "%.2f", -100, 100., 1., 0.);
IUFillNumberVector(&TemperatureNP, TemperatureN, 1, getDeviceName(), "FOCUS_TEMPERATURE", "Temperature", MAIN_CONTROL_TAB,
IP_RO, 0, IPS_IDLE );

// Temperature offset
IUFillNumber(&TemperatureOffsetN[0], "OFFSET", "Offset", "%.2f", -15, 15., 1., 0.);
IUFillNumberVector(&TemperatureOffsetNP, TemperatureOffsetN, 1, getDeviceName(), "TEMPERATURE_OFFSET", "Temperature",
MAIN_CONTROL_TAB, IP_WO, 0, IPS_IDLE );

// Motor Step Delay
IUFillNumber(&FocusStepDelayN[0], "FOCUS_STEP", "Value", "%.f", 7, 100., 1., 7.);
IUFillNumberVector(&FocusStepDelayNP, FocusStepDelayN, 1, getDeviceName(), "FOCUS_STEP_DELAY", "Step Rate", SETTINGS_TAB,
IP_RW, 0, IPS_IDLE );


On the other hand I can't find the function that kstars sends to the arduino to tell it to do the GoHome

I'm not sure if you have the time to do it, but I'm sure you can figure out how to do it, so I'm not sure if you have the time.

Thanks again
Christophe
2 years 5 months ago #76637

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

  • Posts: 250
  • Thank you received: 3
Hello
One more question Jasem, how do I rename the driver that I modify so that I still have the original.
How do I install the modified driver and with which file do I have to do it?

Thanks again.
2 years 5 months ago #76646

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

You can rename the source files, and then look for nightcrawel in CMakeLists.txt and just copy the section for it and rename everything accordingly.

Regarding the driver, you need to make it only inherit INDI::Rotator, so remove INDI::FocuserInterface and all the Focuser related functions and variables. Alternatively, you can create a new driver based off one of the existing Rotator drivers.
2 years 5 months ago #76659

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

  • Posts: 250
  • Thank you received: 3
hello Jasem
so I'll try to modify the driver and remove the parts that I think are useless.
But where can I see the commands in the driver, that it sends to the arduino, because I need to find the "home" command of the rotator, and the command to give an angle from the serial terminal of the IDE, to control the modicication of the code without going through kstars for my tests.

And thank you for the link to the other rotator drivers, but is there also one online for the arduino.

Thanks again.
2 years 5 months ago #76661

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

  • Posts: 250
  • Thank you received: 3
sorry again,
but I didn't quite understand that
**
You can rename the source files, and then look for nightcrawel in CMakeLists.txt and just copy the section for it and rename everything accordingly.
**
what should I do?
I just have to find the files, copy them, modify and rename them ?
or do I have to make a new driver by modifying the original files ?
2 years 5 months ago #76662

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

You have two files, nightcrawler.h and .cpp. Copy them to something like myrotator.h and .cpp

In INDI CMakelists.txt, search for the nightcrawler section where it builds the executable. Just copy it and change the the source files and the executable (e.g. indi_myrotator_rotator). Also, edit drivers.xml and add an entry there for your rotator.
2 years 5 months ago #76663

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

Time to create page: 1.218 seconds