PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Motor Library wechseln



flyingeagle1975
29.05.2014, 05:22
Hallo,

Ich habe folgendes Problem. Ich baue gerade für mein Teleskop ein Filterrad.
Mit diesem Filterrad ist es möglich mit der s/w CCD Kamera Farbaufnahmen zu machen.
In diesem Rad sind dazu 5 Filter angebracht. Zu jedem Filter ist ein Magnet zur Positionsermittlung vorhanden. Vier Filter mit Nördlicher Ausrichtung ,und zum Indexieren des Nullpunktes bzw. dem ersten Filter mit Südlicher Ausrichtung. Erfaßt werden sie über einen Hall Sensor. Zur Hardware habe ich einen Arduino Uno und einen baugleichen Adafruit Stepper/Servo Shield.
Gesteuert wird das ganze dann über ein Plugin für das Aufnahmeprogramm.
Ich habe schon die komplette Firmware für das Arduino und auch das Plugin, leider arbeitet die Firmware mit der Stepper Library. Und so wie es aussieht kann ich mit dem Motorshield nur die AFMotor Library nutzen. Leider bin ich beim Programmieren noch ein blutiger Anfänger, aber wenn ich jetzt anfange ein eigenes Programm samt Plugin zu schreiben vergehen wohl Jahre. Bin seit mittlerweile 2 Wochen durchgängig schon am Lernen, aber irgendwie stellen sich mir mehr fragen als ich Antworten bekomme.
Klar möchte ich nebenbei ein wenig Programmieren lernen, aber Ich würde gerne dieses Filterrad auch noch recht schnell fertigbekommen. Bin eigentlich mehr der Basteler als Programmierer Big Grin
Ich hoffe mir kann da jemand helfen.
Dabei noch ein Foto vom aktuellen Baustatus sowie der Originalcode

Viele Grüße

Micha


/*
* Filterwheel
* Provides for control of a five position filter wheel.
*
* Copyright (C) 2014 Howard Dutton
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*
* Revision History
*
* Date Version Comment
* 03-16-2014 1.0 Adaptation of Camera/Filterwheel driver to filterwheel only
* 05-26-2014 1.1 Added code at adjust the stepping granularity
*
* Author: Howard Dutton
* http://www.stellarjourney.com
*
*
*/

#include "stdio.h";
#include "EEPROM.h";
#include <Stepper.h>

#define fullRotation 280 // enough slots to hold reading a bit more than once around the wheel (for finding index/calibration), keep under about 1000
#define stepGranularity 8 // number of half-steps per slot

boolean debug = false;
boolean override = false;

Stepper myStepper(96,2,3,4,5,true); // Note: the Stepper library in the Arduino enviroment needs to be replaced with a half-stepping version
// this can be found at http://code.google.com/p/arduino/issues/detail?id=139 and might need to be modified
// by replacing the line #include "WProgram.h" with #include "Arduino.h"

int hallAnalogPin =1; // analog in A1

int filter_position =0; // filter position control
int filters_to_pass =0; // number of filters to pass to arrive at the destination
int filter_destination =0; //
int filter_offset =0; // moves +/- once we find the correct filter to center it
int filter_hysteresis =0; // ignore this many readings when the filter wheel begins to rotate (prevents false counts)

boolean standardFilter =false; // keep track of filter wheel state
boolean indexFilter =false;
int Moving =0;
int calibrateFilters =0;
boolean zeroFilters =false;

int G =512; // for processing magnetic gauss readings
int G1 =512; // for determination of filter positions
int neutralG =100;
int southG =75;
int northG =125;
int thresholdGS;
int thresholdGN;
byte GA[fullRotation]; // holds a series of gauss readings for calibration of the filter wheel

char inChar;
char buffer[80]; // storage for command
int bufferPtr =0; // current location in buffer
char buffer2[3]; // two letter command code
char buffer3[13]; // numeric tail
boolean commandError; // command status

void setup() // run once, when the sketch starts
{
int l;

// slow pwm down
TCCR1B = TCCR1B & 0b11111000 | 0x01; // clock divided by 1024

// get the stepper ready
myStepper.setSpeed(20);

// make the ADC use our external voltage reference
analogReference(EXTERNAL);

// enable serial communications
Serial.begin(9600);
Serial.flush();

// retrieve the last filter position
filter_position=EEPROM.read(0);
if (filter_position<0) filter_position=0;
if (filter_position>4) filter_position=0;
filter_destination=filter_position;
filters_to_pass=0;

// retrieve the filter offset position
filter_offset=EEPROM.read(1)-10;
if (filter_offset<-10) filter_offset=-10;
if (filter_offset> 10) filter_offset= 10;

// retrieve the last filter wheel calibration
southG =EEPROM_readInt(20);
northG =EEPROM_readInt(22);
neutralG=EEPROM_readInt(24);

// prepare the command buffers
buffer[0]=0;
buffer2[0]=0;
buffer3[0]=0;
}

void loop()
{
bool input_ready = false;
int dummy;
int State;
int T;
int i;
int L;
int tr_count_actual;
char Temp[80];

// build serial input:
if (Serial.available() > 0) {

// get incoming byte:
inChar = Serial.read();

// and build up a command
buffer[bufferPtr]=toupper(inChar);
bufferPtr++;
buffer[bufferPtr]=(char)0;
if (bufferPtr>78) { bufferPtr=78; } // limit maximum command length to avoid overflow

// process command
if (inChar==(char)13) {
buffer[bufferPtr-1]=0; // erase the cr
strncpy(buffer2,buffer,2); // get the two letter command
strncpy(buffer3,&buffer[2],12); // get the optional numeric tail

commandError=false;

// ask for version
if (strcmp(buffer2,"V?") == 0) {
if (strlen(buffer3)==0) { Serial.println("On-Cue Filter Wheel V1.0"); } else commandError=true;
} else

// set current filter 1
if (strcmp(buffer2,"F1") == 0) {
if ((strlen(buffer3)==0) && (!Moving)) {
if (filter_position!=0) { filters_to_pass=toPass(0,filter_position); filter_destination=0; filter_hysteresis=10; Moving=300; }
Serial.println("Selecting Filter #1");
} else commandError=true;
} else
// set current filter 2
if (strcmp(buffer2,"F2") == 0) {
if ((strlen(buffer3)==0) && (!Moving)) {
if (filter_position!=1) { filters_to_pass=toPass(1,filter_position); filter_destination=1; filter_hysteresis=10; Moving=300; }
Serial.println("Selecting Filter #2");
} else commandError=true;
} else
// set current filter 3
if (strcmp(buffer2,"F3") == 0) {
if ((strlen(buffer3)==0) && (!Moving)) {
if (filter_position!=2) { filters_to_pass=toPass(2,filter_position); filter_destination=2; filter_hysteresis=10; Moving=300; }
Serial.println("Selecting Filter #3");
} else commandError=true;
} else
// set current filter 4
if (strcmp(buffer2,"F4") == 0) {
if ((strlen(buffer3)==0) && (!Moving)) {
if (filter_position!=3) { filters_to_pass=toPass(3,filter_position); filter_destination=3; filter_hysteresis=10; Moving=300; }
Serial.println("Selecting Filter #4");
} else commandError=true;
} else
// set current filter 5
if (strcmp(buffer2,"F5") == 0) {
if ((strlen(buffer3)==0) && (!Moving)) {
if (filter_position!=4) { filters_to_pass=toPass(4,filter_position); filter_destination=4; filter_hysteresis=10; Moving=300; }
Serial.println("Selecting Filter #5");
} else commandError=true;
} else
// ask for current filter position
if (strcmp(buffer2,"F?") == 0) {
if (strlen(buffer3)==0) {
if ((filter_position!=filter_destination) || (Moving)) {
sprintf(Temp,"Filter: ?");
} else {
if (debug) {
sprintf(Temp,"Filter: %d, Offset: %d, thresholdGN: %d, neutralG: %d, thresholdGS: %d", filter_position, filter_offset, thresholdGN, neutralG, thresholdGS);
} else {
int fp=filter_position+2; if (fp>4) fp=fp-4;
sprintf(Temp,"Filter: %d", fp);
}
}
Serial.println(Temp);
} else commandError=true;
} else
// ask to calibrate filter wheel
if (strcmp(buffer2,"FC") == 0) {
if ((strlen(buffer3)==0) && (!Moving)) { calibrateFilters=fullRotation; Moving=300; filter_hysteresis=0; Serial.println("Ok"); } else commandError=true;
} else
// ask to seek zero position on filter wheel
if (strcmp(buffer2,"FZ") == 0) {
if ((strlen(buffer3)==0) && (!Moving)) { zeroFilters=fullRotation; Moving=300; filter_hysteresis=6; Serial.println("Ok"); } else commandError=true;
} else
// tweek filter wheel +
if (strcmp(buffer2,"F+") == 0) {
if (strlen(buffer3)==0) {
if (filter_offset<9) { filter_offset++; EEPROM.write(1,filter_offset+10); Serial.println("Filter Offset Adjusted +1"); } else commandError=true;
} else commandError=true;
} else
// tweek filter wheel -
if (strcmp(buffer2,"F-") == 0) {
if (strlen(buffer3)==0) {
if (filter_offset>-9) { filter_offset--; EEPROM.write(1,filter_offset+10); Serial.println("Filter Offset Adjusted -1"); } else commandError=true;
} else commandError=true;
} else

// debug mode on
if (strcmp(buffer2,"D+") == 0) {
if (strlen(buffer3)==0) { debug=true; Serial.println("Debug mode on"); } else commandError=true;
} else
// debug mode off
if (strcmp(buffer2,"D-") == 0) {
if (strlen(buffer3)==0) { debug=false; Serial.println("Debug mode off"); } else commandError=true;
} else {
// command not recognized
commandError=true;
Serial.println("Error");
}

// clear the last command
bufferPtr=0; buffer[bufferPtr]=0;
}
}

// Hall-effect filter wheel sensor
// Some initial values observed were
// SouthG = 794
// NeutralG = 635
// NorthG = 584
G=analogRead(hallAnalogPin);
thresholdGN=(neutralG-((neutralG-northG)/2)); // ex. 635-584 = +51, 51/4 = 15, 635-15 = 620;
thresholdGS=(neutralG-((neutralG-southG)/2)); // ex. 635-794 = -159, -159/4 = -40, 635+40 = 675;
if ((G<thresholdGN) && (G1>=thresholdGN) && !filter_hysteresis) { indexFilter =true; } else { indexFilter=false; }
if ((G>thresholdGS) && (G1<=thresholdGS) && !filter_hysteresis) { standardFilter=true; } else { standardFilter=false; }
G1=G;

if (debug) {
if (indexFilter) { Serial.print("I="); Serial.println(G); }
if (standardFilter) { Serial.print("S="); Serial.println(G); }
if (filter_hysteresis) { Serial.print("H="); Serial.println(G); }
}

if (filter_hysteresis>0) filter_hysteresis--;

if (Moving) {
// Three modes of operation, mode 1: filter positioning
if ((!zeroFilters) && (!calibrateFilters)) {
// Standard or index filter found
if (standardFilter || indexFilter) {
if (filters_to_pass>0) filters_to_pass--;
}
// Move filter to the new position
if (filters_to_pass>0) {
if (Moving>0) Moving--;
myStepper.step(stepGranularity);
} else {
if (filter_position!=filter_destination) {
filter_position=filter_destination;
EEPROM.write(0,filter_position);
}
myStepper.step(filter_offset*stepGranularity);
filter_hysteresis=false;
Moving =false;
}
}

// Three modes of operation, mode 2: homing
if ((zeroFilters) && (!calibrateFilters)) {
// Index filter found
if (indexFilter) {
filter_position=0; filter_destination=0;
EEPROM.write(0,filter_position);
myStepper.step(filter_offset*stepGranularity));
Moving=false;
} else {
// move filter to a new position
if (zeroFilters>0) zeroFilters--;
if (Moving>0) Moving--;
myStepper.step(stepGranularity);
}
}

// Three modes of operation, mode 3: calibration
if ((!zeroFilters) && (calibrateFilters)) {
if (calibrateFilters>2) {
// save a series of readings from all around the wheel
if (calibrateFilters>1) calibrateFilters--;
if (Moving>0) Moving--;
myStepper.step(stepGranularity);
GA[calibrateFilters]=(G>>2);
} else {
// sort the list of readings, ascending
int l;
int m;
for (l=1; l<fullRotation-1; l++) {
for (m=1; m<fullRotation-1; m++) {
if (GA[l]>GA[m]) { G=GA[l]; GA[l]=GA[m]; GA[m]=G; }
}
}

// take an average of readings from the lowest, middle, and highest
southG =((GA[2]+GA[3]+GA[4])/3)<<2;
neutralG=((GA[fullRotation/2-1]+GA[fullRotation/2]+GA[fullRotation/2+1])/3)<<2;
northG =((GA[fullRotation-3]+GA[fullRotation-4]+GA[fullRotation-5])/3)<<2;

if (debug) {
Serial.println("Cal complete:");
for (l=1; l<fullRotation-1; l++) { Serial.println(GA[l]<<2); }
Serial.println("");
sprintf(Temp,"Sav: SouthG=%d NeutralG=%d NorthG=%d",southG,neutralG,northG);
Serial.println(Temp);
}

// and save them for later
EEPROM_writeInt(20,southG);
EEPROM_writeInt(22,northG);
EEPROM_writeInt(24,neutralG);

calibrateFilters=false;
Moving =false;
}
}
} else {
filter_hysteresis=false;
zeroFilters =false;
Moving =false;
calibrateFilters=false;
filters_to_pass=0;
}
}

// get the numeric tail of the command
boolean intTail2(int *val,int *dec, int low, int high) {
int l;
int i;
int hasDecimal;
boolean isNumeric;
long temp;

l = strlen(buffer3);
if (l>0) {
// check to make sure we have a number
isNumeric=true; for (i=0; i++; i<l) { if (((buffer3[i]<'0') || (buffer3[i]>'9')) && (buffer3[i]!='.')) { isNumeric=false; } }

// check that only one digit is after the decimal point, if any decimal point is found
hasDecimal=0; for (i=0; i++; i<l) { if (buffer3[i]=='.') { hasDecimal++; } }
if (hasDecimal>1) { isNumeric=false; }
if ((hasDecimal==1) && (buffer3[l-2]!='.')) { isNumeric=false; }

// record and strip the decimal if present
*dec=0;
if (hasDecimal) { *dec=(int)buffer[l-1]-48; buffer[l-2]=0; }

// convert to an integer
*val=0;
if (isNumeric) {
temp=atoi(buffer3);
if ((temp>=low) and (temp<=high)) { *val=temp; return true; } else return false;
} else return false;

} else return false;
}

// calculate how many filters to pass from current position
int toPass(int filterDestination, int filterPosition) {
int l;
l=filterDestination-filterPosition;
// if (l<0) l=4+l; // for a 4-position wheel
if (l<0) l=5+l;
return l;
}

// write int numbers into EEPROM
void EEPROM_writeInt(int i,int l) {
byte *lPtr;
lPtr = (byte*)&l;
EEPROM.write(i+0,*lPtr); lPtr++;
EEPROM.write(i+1,*lPtr);
}

// read int numbers from EEPROM
int EEPROM_readInt(int i) {
int l;
byte *lPtr;
lPtr = (byte*)&l;
*lPtr=EEPROM.read(i+0); lPtr++;
*lPtr=EEPROM.read(i+1);
return l;
}