Jump to content

Banner.jpg.b89429c566825f6ab32bcafbada449c9.jpg

Arduino Ascom focuser Mark2


tekkydave

Recommended Posts

I was kinda wondering if the ASCOM focuser could be extended to work with more than one scope at a time but I think this is probably asking too much :D

I think the issue is that you can only have one instance of each ascom driver running at once. You would need to create a copy of the AAF2 driver with a different name (e.g. AAF2b) to connect the second focuser to. I think that's correct. Ascom experts please comment :grin:

I think some commercial focusers do just that.

Link to comment
Share on other sites

I had a look at your eeprom code but believe you have some serious issues.

EEPROM in the controller is somewhat limited to 10,000 writes.

The way the code is written, this could be very quickly reached?

As example, put a little counter in that increments each time the eeprom is written, then do an imaging session and at the end of the night just print out/dump how many times it was written (might need another serial command) - then divide 10,000 by that number and what do you get? The number of sessions before the eeprom will likely fail?

Cheers

Robert

  • Like 1
Link to comment
Share on other sites

Suggest the following code snippets for the eeprom

#include <EEPROM.h>                   // needed for EEPROM
#include "eepromanything.h"           // needed for EEPROM
// #define EEPROMSIZE 500              // ATMEGA168 512 EEPROM
#define EEPROMSIZE 1000               // ATMEGA328P 1024 EEPROM
// these are stored in EEPROM - all variables in a structure
struct config_t {
  int validdata;       // if this is 99 then data is valid
  int fposition;       // last focuser position
  int maxstep;         // max steps
} myfocuser;
int datasize;      // will hold size of the struct myfocuser - 6 bytes
int nlocations;    // number of storage locations available in EEPROM
int currentaddr;   // will be address in eeprom of the data stored
bool writenow;     // should we update values in eeprom
bool found;        // did we find any stored values?
long previousMillis = 0;   // used as a delay whenever the EEPROM settings need to be updated
long interval = 10000;     // interval in milliseconds to wait after a move before writing settings to EEPROM, 10s
long numwrites = 0;        // number of eeprom writes this session
// Default initial positions if not set/overriden by Ascom Driver or Winapp
int currentPosition = 5000;   // current position
int targetPosition = 5000;    // target position
int maxFocuserLimit = 32000;  // arbitary focuser limit
int maxSteps = 10000;         // maximum position of focuser
int maxIncrement = 1000;      // maximum number of steps permitted in one move
int minimumPosition = 0;      // minimum position to avoid focuser damage
boolean isMoving = false;        // is the motor currently moving
// Setup
void setup() {
  // initialize serial for ASCOM
  ...............
  found = false;
  writenow = false;
  datasize = sizeof( myfocuser );    // should be 6
  nlocations = EEPROMSIZE / datasize;  // for AT328P = 1000 / 6 = 166 locations
  numwrites = 0;
  
  for (int lp1 = 0; lp1 < nlocations; lp1++ ) {
    int addr = lp1 * datasize;
    EEPROM_readAnything( addr, myfocuser );
    // check to see if the data is valid
    if ( myfocuser.validdata == 99 ) {
      // data was erased so write some default values
      currentaddr = addr;
      found = true;
    }
  }
  if ( found == true ) {
    // set the focuser back to the previous settings
    // done after this in one hit
    // mark current eeprom address as invalid and use next one
    // each time focuser starts it will read current storage, set it to invalid, goto next location and
    // write values to there and set it to valid - so it doesnt always try to use same locations over and
    // over and destroy the eeprom
    // using it like an array of [0-nlocations], ie 100 storage locations for 1k EEPROM
    EEPROM_readAnything( currentaddr, myfocuser );
    myfocuser.validdata = 0;
    EEPROM_writeAnything(currentaddr, myfocuser);    // update values in EEPROM
    numwrites++;
    
    // goto next free address and write data
    currentaddr += datasize;
    // bound check the eeprom storage and if greater than last index [0-EEPROMSIZE-1] then set to 0
    if ( currentaddr >= (nlocations * datasize) ) currentaddr = 0;
    myfocuser.validdata = 99;
    EEPROM_writeAnything(currentaddr, myfocuser);    // update values in EEPROM
    numwrites++;
  }
  else {
    // set defaults because not found
    myfocuser.validdata = 99;
    myfocuser.maxstep = 10000;
    myfocuser.fposition = 5000;
    // now write the data to EEPROM
    EEPROM_writeAnything(currentaddr, myfocuser);    // update values in EEPROM
    numwrites++;
  }
  // Set focuser defaults from saved values in EEPROM.
  currentPosition = myfocuser.fposition;
  targetPosition = myfocuser.fposition;
  maxSteps = myfocuser.maxstep;
  .......
}
// Main Loop
void loop() {
  // Move the position by a single step if target is different to current position
  if (targetPosition != currentPosition) {
    isMoving = true;
    writenow = true;             // updating of EEPROM ON
    previousMillis = millis();    // keep updating previousMillis whilst focuser is moving
  } 
  else {
    // focuser is NOT moving now, move is completed
    isMoving = false;
    if ( writenow == true ) {    // time to update eeprom
      // decide if we have waited 10s after the last move, if so, update the EEPROM
      unsigned long currentMillis = millis();
      if ( (currentMillis - previousMillis > interval) && (writenow == true) ) {
        previousMillis = currentMillis;    // update the timestamp
        // copy current settings and write the data to EEPROM
        myfocuser.validdata = 99;
        myfocuser.fposition = currentPosition;
        myfocuser.maxstep = maxSteps;
        EEPROM_writeAnything(currentaddr, myfocuser);    // update values in EEPROM
        numwrites++;
        writenow = false;
      }
    }
    clearOutput(); // release the stepper coils to save power
  }
}
  • Like 1
Link to comment
Share on other sites

Suggest the following code snippets for the eeprom

#include <EEPROM.h>                   // needed for EEPROM
#include "eepromanything.h"           // needed for EEPROM
// #define EEPROMSIZE 500              // ATMEGA168 512 EEPROM
#define EEPROMSIZE 1000               // ATMEGA328P 1024 EEPROM
// these are stored in EEPROM - all variables in a structure
struct config_t {
  int validdata;       // if this is 99 then data is valid
  int fposition;       // last focuser position
  int maxstep;         // max steps
} myfocuser;
int datasize;      // will hold size of the struct myfocuser - 6 bytes
int nlocations;    // number of storage locations available in EEPROM
int currentaddr;   // will be address in eeprom of the data stored
bool writenow;     // should we update values in eeprom
bool found;        // did we find any stored values?
long previousMillis = 0;   // used as a delay whenever the EEPROM settings need to be updated
long interval = 10000;     // interval in milliseconds to wait after a move before writing settings to EEPROM, 10s
long numwrites = 0;        // number of eeprom writes this session
// Default initial positions if not set/overriden by Ascom Driver or Winapp
int currentPosition = 5000;   // current position
int targetPosition = 5000;    // target position
int maxFocuserLimit = 32000;  // arbitary focuser limit
int maxSteps = 10000;         // maximum position of focuser
int maxIncrement = 1000;      // maximum number of steps permitted in one move
int minimumPosition = 0;      // minimum position to avoid focuser damage
boolean isMoving = false;        // is the motor currently moving
// Setup
void setup() {
  // initialize serial for ASCOM
  ...............
  found = false;
  writenow = false;
  datasize = sizeof( myfocuser );    // should be 6
  nlocations = EEPROMSIZE / datasize;  // for AT328P = 1000 / 6 = 166 locations
  numwrites = 0;
  
  for (int lp1 = 0; lp1 < nlocations; lp1++ ) {
    int addr = lp1 * datasize;
    EEPROM_readAnything( addr, myfocuser );
    // check to see if the data is valid
    if ( myfocuser.validdata == 99 ) {
      // data was erased so write some default values
      currentaddr = addr;
      found = true;
    }
  }
  if ( found == true ) {
    // set the focuser back to the previous settings
    // done after this in one hit
    // mark current eeprom address as invalid and use next one
    // each time focuser starts it will read current storage, set it to invalid, goto next location and
    // write values to there and set it to valid - so it doesnt always try to use same locations over and
    // over and destroy the eeprom
    // using it like an array of [0-nlocations], ie 100 storage locations for 1k EEPROM
    EEPROM_readAnything( currentaddr, myfocuser );
    myfocuser.validdata = 0;
    EEPROM_writeAnything(currentaddr, myfocuser);    // update values in EEPROM
    numwrites++;
    
    // goto next free address and write data
    currentaddr += datasize;
    // bound check the eeprom storage and if greater than last index [0-EEPROMSIZE-1] then set to 0
    if ( currentaddr >= (nlocations * datasize) ) currentaddr = 0;
    myfocuser.validdata = 99;
    EEPROM_writeAnything(currentaddr, myfocuser);    // update values in EEPROM
    numwrites++;
  }
  else {
    // set defaults because not found
    myfocuser.validdata = 99;
    myfocuser.maxstep = 10000;
    myfocuser.fposition = 5000;
    // now write the data to EEPROM
    EEPROM_writeAnything(currentaddr, myfocuser);    // update values in EEPROM
    numwrites++;
  }
  // Set focuser defaults from saved values in EEPROM.
  currentPosition = myfocuser.fposition;
  targetPosition = myfocuser.fposition;
  maxSteps = myfocuser.maxstep;
  .......
}
// Main Loop
void loop() {
  // Move the position by a single step if target is different to current position
  if (targetPosition != currentPosition) {
    isMoving = true;
    writenow = true;             // updating of EEPROM ON
    previousMillis = millis();    // keep updating previousMillis whilst focuser is moving
  } 
  else {
    // focuser is NOT moving now, move is completed
    isMoving = false;
    if ( writenow == true ) {    // time to update eeprom
      // decide if we have waited 10s after the last move, if so, update the EEPROM
      unsigned long currentMillis = millis();
      if ( (currentMillis - previousMillis > interval) && (writenow == true) ) {
        previousMillis = currentMillis;    // update the timestamp
        // copy current settings and write the data to EEPROM
        myfocuser.validdata = 99;
        myfocuser.fposition = currentPosition;
        myfocuser.maxstep = maxSteps;
        EEPROM_writeAnything(currentaddr, myfocuser);    // update values in EEPROM
        numwrites++;
        writenow = false;
      }
    }
    clearOutput(); // release the stepper coils to save power
  }
}

Thanks for pointing that out. I'll sort it out in the next release.

Dave

Link to comment
Share on other sites

I had a look at your eeprom code but believe you have some serious issues.

EEPROM in the controller is somewhat limited to 10,000 writes.

The way the code is written, this could be very quickly reached?

As example, put a little counter in that increments each time the eeprom is written, then do an imaging session and at the end of the night just print out/dump how many times it was written (might need another serial command) - then divide 10,000 by that number and what do you get? The number of sessions before the eeprom will likely fail?

Cheers

Robert

Is it the whole EEPROM that will fail or just the memory addresses I am using?

Link to comment
Share on other sites

There is one more approach.

On address PosOffset in the EEPROM are reserved 2 bytes. They keep the memory address where the position is stored. So when you need to store the position it uses the address, writes the value, then reads it back and if it is no the same, then increase the address PosOffset with two more bytes and start to use a new cell :)

Here is my code:

void WritePosition(unsigned int Value)
{
    unsigned int Address = ReadTwoBytes(PosOffset);   
    WriteTwoBytes(Address, Value);   
   
    if(Value != ReadTwoBytes(Address))
    {
        WriteTwoBytes(PosOffset, Address+2);
        WriteTwoBytes(Address, Value);
    }
}

So It is important to place the first PosOffset to point after all other stored variables in order to be able to use the rest of the EEPROM. Also you can increase the life of the cells by using timer that is started on button press and when the button is released to store the position just once ;)

  • Like 1
Link to comment
Share on other sites

That is very useful for using the EEPROM for any project - thank you :)  I use EEPROM on some of my other projects and was aware that the number of writes was limited and cut down how many times it was written by only writing when necessary.  The above contains other ideas and will be very useful :)

Link to comment
Share on other sites

Nice to see more input in this thread even if I don't understand it, thanks to all -  brown_rb, gina, dave as usual and Ivo.

While I am here - Ivo, do you have an opinion on auto focus ?  should this be in the ascom driver or in something like APT the application ?  :smiley:  :smiley:.  it has been asked in this thread before and I know I can set an alert in APT on temperature change to suggest I check focus ......... ?  

Link to comment
Share on other sites

Thanks Mick!

As I know all focusers that has temperature sensor are offering in driver/controller temperature compensation, but my opinion is that the right place is in the imaging application, because the action can be made between the exposures :)

  • Like 3
Link to comment
Share on other sites

Thanks everyone for their input especially re the eeprom lifetime issue. I'll fix the issue asap but it may be a couple of weeks. I have some other improvements to the sketch that I have already mentioned and some fixes to the driver in development so watch this space :grin:

  • Like 1
Link to comment
Share on other sites

Updated Roll of Honour

Here is an updated list of SGLers who have built the AAF2 focuser. Well done to all. Hope I haven't missed anyone.

Dave_D

Baffa

wuthton

Mick J

russellhq

mindburner

Davey-T

iwannabswiss

silios

SUNJiaLin

blackdragon72

redtail

SnakeyJ

  • Like 2
Link to comment
Share on other sites

Quite an impressive list :)  I'm hoping to add myself before long.  The Esprit 80ED seems to hold focus very well but I'm trying other scopes/lenses and they might not.

  • Like 1
Link to comment
Share on other sites

I an not sure that temp comp should be in the imaging app. It is better to have it in the driver as temperatures can change quite rapidly during a long sub. The amounts of change are small - in the microns - and a good focuser doesn't shift the image during focusing.

/per

Link to comment
Share on other sites

I an not sure that temp comp should be in the imaging app. It is better to have it in the driver as temperatures can change quite rapidly during a long sub. The amounts of change are small - in the microns - and a good focuser doesn't shift the image during focusing.

/per

I agree. The driver is there to hide the hardware's real physical operation from the client application. Putting the temp-comp in the driver will make it work with any ascom-compliant application. However if you have written a great app and none of you customers drivers support it you might want to build it into your app instead. If I was writing an imaging app I might be tempted to put it there so all my users can benefit, but I would also allow them to use their focuser drivers built-in temp-comp if they prefer.
Link to comment
Share on other sites

Don't get me wrong :) I don't say that there is no need to implement the compensation in the controller/driver... Just if the imaging application is capable I would use it...

BTW keep in mind that optics are inert and react relatively slow to the temperature changes. Wind gust will give rapid changes of the temperature reading, but this doesn't mean that focus is changing. A good approach is to average the readings for certain period and then to decide if there is need to change the focus :)

Link to comment
Share on other sites

Exactly! I would use at least a five minute sliding average (and will in my own focuser design) ;) - in the driver, naturally (hehe).

/per

Dave included the temperature sensor, I built it and now, measure the temperature well.

- But, where to put this sensor ? (in the box with arduino nano? ouside close to the stepper ? external part of the focuser or on the body of the optical train ?

In fact, we don't really care about temperature, what we want to control is material dilatation related to focus zone. 

So, which part of the optical train is the more sensistive to dilatation ? 

Didier S-C

Link to comment
Share on other sites

I'm using the 12v version of the 28BYJ-48 running off the 13.8v supply.

Gina - I've orded a couple of the 12v 28BYJ-48's (now currently on the slow boat from PRC), but wonder if you have varied the circuit diagram to give a direct supply to the motors.     Dave's circuit diagram below:

post-26731-0-33743200-1417467681_thumb.p

Shows the power supply to the motor as common with 9V supplied to the Arduino GND 29 and VIN 30.   Will I fry the nano by putting 13.8V across this?  Or have you modified the circuit to just supply the 13.8V to the ULN2003?

There should be sufficient juice from my Startech hub to provide the 5V DC for the nano's logic.

Link to comment
Share on other sites

I'm powering the Arduino from the USB.  I read that powering an Arduino Mega (which I'm using for my main rig) from Vin disables the USB to serial interface chip and that to use the USB for either computer control or as a display, requires that the power is supplied via the USB connection rather than Vin.

The ULN2003As and stepper motors are powered directly from the 13.8v supply (via a fuse).

Arduino Nano data :-

Input Voltage (recommended) 7-12 V

Input Voltage (limits) 6-20 V

The Arduino Nano can be powered via the Mini-B USB connection, 6-20V unregulated external power supply (pin 30), or 5V regulated external power supply (pin 27). The power source is automatically selected to the highest voltage source.

The FTDI FT232RL chip on the Nano is only powered if the board is being powered over USB. As a result, when running on external (non-USB) power, the 3.3V output (which is supplied by the FTDI chip) is not available and the RX and TX LEDs will flicker if digital pins 0 or 1 are high.

Edited by Gina
  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • 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.