/*
StativoStativo Firmware 0.9
Stand: 05.12.2013 16:20
FEHLER IM CODE:
KEINE
Legende der Status LED:
GRUEN: Betriebsbereit. Motorsteuerung aktiv. Auf Aktion durch Nutzer wartend.
GELB: Aktiv. Anfahren der Startposition/Standbyeposition.
ORANGE: Aktiv. Startposition angefahren. Start der Nachfuehrung nach CAMIntervall.
ROT: Aktiv. Nachfuehrung und Kamerasteuerung aktiv.
BLAU: Pausiert. Ueberhitzung. Luefterdrehzahl auf 100%. Wiederherstellung der Betriebstemperatur. Anfahren der Startposition nach Abkühlung.
by Simon Krause und Alexander Schulz
*/
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "OneButton.h" //OneButton Bibliothek implementiert
#include "multiCameraIrControl.h" //multiCameraIrControl Bibliothek implementiert
#include "AccelStepper.h" //AccelStepper Bibliothek implementiert
#include "math.h" // Math Bilibothek implementiert
typedef enum {
ACTION_NONE, //Steuerung aus - LEDs aus
ACTION_ON, //Steuerung betriebsbereit - gruene LED ein
ACTION_1, //Steuerung aktiv - Nachfuehrung betreibsbereit/aktiv - gelbe/orange/rote LED ein
ACTION_2, //Motor auf Standbyestellung - gelbe LED ein
}
MyActions;
MyActions nextAction = ACTION_NONE; //Steuerung bei Start aus
#define EVER (;
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//---------------------------KALIBRIERUNG----------------------------
long startposition = -8000; //Startposition in Mikroschritten
long runposition = 8000; //Anschlag der Nachfuehrung in Mikroschritten
int VR = 100; //Geschwindigkeit der Nachfuehrung
int VB= 4500; //Geschwindigkeit der Positionsanfahrung
unsigned long IRIntervall = 5000; //Intervall der IR-LED
unsigned int CAMIntervall = 5000; //Zeit bis zur Aktivierung der Nachfuehrung
int maxtemp = 50; //Maximale Temperatur des Spannungsreglers
float fanmintemp = 27; //minimale Temperatur der stufenlosen Lueftersteuerung
float fanmaxtemp = 35; //maximale Temperatur der stufenlosen Lueftersteuerung
//------------------------------MOTOR---------------------------------
AccelStepper stepper(1,3,2); //Motor Pins an 2 und 3
long steps; //Speicherung der aktuellen Position
boolean counted = false; //Hilfvariable fuer die Rotatefunktion
float rotatevelo; //Geschwindigkeit des Motors
int rotatecounter = 0; //Hilfsvariable fuer die Rotatefunktion
//-------------------------HILFSVARIABLEN-----------------------------
int i; //Variable zur Aktivierung einzelner Sub-Aktionen
int status; //Variable zur Aktivierung/Deaktivierung einzelner Aktionen
unsigned long previousmillis = 0; //Hilfsvariable fuer Steuerung der IR-LED
int photo; //Anzahl der aufgenommenen Fotos
unsigned long PIntervall; //Hilfsvariable fuer verzoegerte Nachfuehrung
//------------------------LUEFTERSTEUERUNG-----------------------------
boolean fanstatus = true; //Lueftersteuerung ein- oder ausschalten
float printtemp; //Aktuelle Temperatur
int fandiftemp = fanmaxtemp - fanmintemp; //Differenz zwischen fanmaxtemp und fanmintemp für stufenlose Lüftersteuerung
boolean overheat = false; //Hilfvariable fuer Steuerung bei Ueberhitzung
//--------------------------STATUSAUSGABE------------------------------
int printsec; //Gesamtzeit der Nachfuehrdauer in Sekunden
int printhours; //Zeit der Nachfuerdauer (nur Stunden)
int printminutes; //Zeit der Nachfuerdauer (nur Minuten)
int printseconds; //Zeit der Nachfuerdauer (nur Sekunden)
String printhoursname; //Name des Stundenausgabe der Nachfühdauer (Stunde/Stunden)
String printminutesname; //Name des Minutenausgabe der Nachfühdauer (Minute/Minuten)
String printsecondsname; //Name des Sekundenausgabe der Nachfühdauer (Sekunde/Sekunde)
//--------------------------KAMERASTEUERUNG----------------------------
Nikon SNikon(4); //IR LED fuer Nikon an PIN 4
Canon SCanon(4); //IR LED fuer Canon an PIN 4
Pentax SPentax(4); //IR LED fuer Pentax an PIN 4
Olympus SOlympus(4); //IR LED fuer Olympus an PIN 4
Sony SSony(4); //IR LED fuer Sony an PIN 4
//--------------------------EIN/AUSGAENGE------------------------------
OneButton button(A1, true); //Taster an PIN A1
#define DIR_PIN 2 //Richtung Easydriver an PIN 2
#define STEP_PIN 3 //Schritt Easydriver an PIN 3
int blue = 5; //blaue LED an PIN 5
int green = 6; //gruene LED an PIN 6
int mstop = 7; //Motorstop
int red = 9; //rote LED an PIN 9
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void setup() {
Serial.begin(9600); //Serialoutput auf Port 9600 aktiviert
pinMode(DIR_PIN, OUTPUT); //PIN 2 als Output
pinMode(STEP_PIN, OUTPUT); //PIN 3 als Output
pinMode(5, OUTPUT); //PIN 5 als Output
pinMode(6, OUTPUT); //PIN 6 als Output
pinMode(7, OUTPUT); //PIN 7 als Output
pinMode(8, OUTPUT); //PIN 8 als Output
pinMode(9, OUTPUT); //PIN 9 als Output
pinMode(10, OUTPUT); //PIN 10 als Output
pinMode(11, OUTPUT); //PIN 11 als Output
stepper.setMaxSpeed(abs(4500)); //maximale Geschwindigkeit des Motors
button.attachClick(myClickFunction); //Klick-Funktion implementiert
button.attachDoubleClick(myDoubleClickFunction); //Doppelklick-Funktion implementiert
} //Ende setup
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void loop() {
steps = stepper.currentPosition(); //Aktuelle Position des Motors in Variable speichern
unsigned long now = millis(); //Aktuelle Zeit in Variable speichern
button.tick(); //Taster ueberpruefen
printtemp = Thermister(analogRead(0)); //Temperatur kontinuierlich aktualisieren
//---------------------------LUEFTERSTEUERUNG---------------------------
if (fanstatus == true) {
if (printtemp >= fanmintemp && printtemp <= fanmaxtemp) { //Stufenlose Lueftersteuerung
analogWrite(10,((floor(185/fandiftemp)*(printtemp-fanmintemp) )+70));
}
else if (printtemp > fanmaxtemp) { //100% Drehzahl bei erhoeter Temperatur
analogWrite(10,255);
}
else {
analogWrite(10,0);
}
}
//-------------------------TEMPERATURAKTIONEN---------------------------
if (printtemp > maxtemp) { //Motorstopp bei Ueberhitzung - blaue LED ein
digitalWrite(mstop, LOW); //Motorsteuerung aus
digitalWrite(blue, HIGH); //Status-LED auf blau
digitalWrite(red, LOW);
digitalWrite(green, LOW);
digitalWrite(11, HIGH); //Buzzer ein
if (overheat == false) { //einmalige Ausgabe der Ueberhitzung
Serial.print("\nAchtung Ueberhitzung! ");
Serial.print("Temperatur: ");
Serial.print(printtemp);
Serial.print(char(176));
Serial.print("C");
Serial.print("\n");
overheat = true;
status = 0;
rotatecounter = 0;
i = 4;
nextAction = ACTION_NONE;
}
}
if (overheat == true && printtemp > (maxtemp-5) && (millis() % 1000 == 0)) { //regelmaessige Ausgabe der Temperatur bei Ueberhitzung
Serial.print("\nTemperatur: ");
Serial.print(printtemp);
Serial.print(char(176));
Serial.print("C");
}
if (overheat == true && printtemp < (maxtemp-5)) { //Aktion nach Wiederherstellung der Betriebstemperatur
Serial.println("\nBetriebstemperatur wiederhergestellt!");
digitalWrite(11, LOW); //Buzzer ausschalten
digitalWrite(blue, HIGH); //Status LED auf weiß
digitalWrite(red, HIGH);
digitalWrite(green, HIGH);
nextAction = ACTION_1; //Steuerung betriebsbereit machen
status = 5;
overheat = false;
}
//-------------------------ACTION_NONE--------------------------
if (nextAction == ACTION_NONE) { //Steuerung aus - LEDs aus
if (i == 3) {
digitalWrite(blue, LOW); //Status-LED aus
digitalWrite(red, LOW);
digitalWrite(green, LOW);
digitalWrite(mstop, LOW); //Motorsteuerung aus
Serial.println("Steuerung aus.");
i=4;
}
}
//--------------------------ACTION_ON---------------------------
else if (nextAction == ACTION_ON) { //Steuerung betriebsbereit - gruene LED ein
if (i == 3) {
Serial.println("Steuerung betriebsbereit.");
digitalWrite(blue, LOW); //Status LED auf gruen
digitalWrite(green, HIGH);
digitalWrite(red, LOW);
digitalWrite(mstop, HIGH); //Motorsteuerung an
status=0;
photo=0;
i=4;
}
}
//--------------------------ACTION_1----------------------------
else if (nextAction == ACTION_1) { //Steuerung aktiv - gelbe/orange/rote LED ein
if (i < 5){ //Anfahren der Startposition - Warten auf Nachfuehrung
if (status == 0) {
Serial.println("Startstellung anfahren");
digitalWrite(blue, LOW); //Status-LED auf gelb
analogWrite(green, 100);
digitalWrite(red, HIGH);
status = 1;
}
if (status == 1) {
rotate(VB,startposition); //Anfahren der Startposition von der Standbyestellung
}
if (status == 2) { //Warten auf Nachfuehrung
Serial.println("Nachfuehrung betriebsbereit. Kamera bereit machen.");
PIntervall = millis();
analogWrite(green, 25); //Status-LED auf orange
digitalWrite(blue, LOW);
digitalWrite(red, HIGH);
status = 3;
}
if (status == 3) { //Wartezeit bis Nachfuehrung
if(millis() - PIntervall > CAMIntervall) {
previousmillis = millis();
Serial.println("Nachfuehrung aktiv.");
i=5;
status=4;
}
}
}
else if (i == 5) { //Nachfuehrung aktiv - Kamerasteuerung aktiv
unsigned long currentmillis = millis();
digitalWrite(green, LOW); //Status-LED auf rot
digitalWrite(blue, LOW);
digitalWrite(red, HIGH);
if(currentmillis - previousmillis > IRIntervall){ //Kamerasteuerung und Statusausgabe
previousmillis = currentmillis;
SNikon.shutterNow(); //Ausloesung der Kamera
SCanon.shutterNow();
SPentax.shutterNow();
SOlympus.shutterNow();
SSony.shutterNow();
photo == photo++; //Anzahl der Fotos um 1 erhoeen
printsec = photo * IRIntervall / 1000;
Serial.println("======================================");
Serial.println("Nachfuehrung aktiv.");
Serial.print(photo);
if (photo == 1){ //Bedingungen fuer das Layout der Statusausgabe
Serial.println(" Foto");
}
else {
Serial.println(" Fotos");
}
printhours = float( (printsec % 86400) /3600);
printminutes = float( (printsec % 3600) /60);
printseconds = float(printsec % 60);
if (printhours == 1) {
printhoursname = " Stunde ";
}
else {
printhoursname = " Stunden ";
}
if (printminutes == 1) {
printminutesname = " Minute ";
}
else {
printminutesname = " Minuten ";
}
if (printseconds == 1) {
printsecondsname = " Sekunde ";
}
else {
printsecondsname = " Sekunden ";
}
Serial.print("Dauer: ");
if (printhours > 0) {
Serial.print(printhours);
Serial.print(printhoursname);
}
if (printminutes > 0) {
Serial.print(printminutes);
Serial.print(printminutesname);
}
if (printseconds > 0) {
Serial.print(printseconds);
Serial.print(printsecondsname);
}
Serial.print("\n"); //Temperatusausgabe
Serial.print("Temperatur: ");
Serial.print(printtemp);
Serial.print(char(176));
Serial.print("C");
Serial.print("\n");
}
if (status == 4){
rotate(VR,runposition); //Nachfuehrung ab Startposition zum Anschlag
}
}
}
//--------------------------ACTION_2----------------------------
else if (nextAction == ACTION_2) { //Anfahren der Standbyestellung - gelbe LED ein
if (i == 3) {
analogWrite(green, 100); //Status-LED auf gelb
digitalWrite(blue, LOW);
digitalWrite(red, HIGH);
if (status == 5) {
Serial.println("Standbyestellung anfahren.");
status = 6;
}
if (status == 6) {
rotate(VB,0); //Anfahren der Standbyestellung
}
}
else if (i==4){ //Steuerung nach Anfahren der Standbyestellung betriebsbereit
myDoubleClickFunction();
}
}
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void myClickFunction() { //Aktionswechsel bei Klick
i=3;
if (nextAction == ACTION_NONE){
nextAction = ACTION_ON;
}
else {
nextAction = ACTION_NONE;
}
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void myDoubleClickFunction() { //Aktionswechsel bei Doppelklick
i=3;
rotatecounter = 0;
if (nextAction == ACTION_ON) {
status = 0;
nextAction = ACTION_1;
}
else if (nextAction == ACTION_1) {
status = 5;
Serial.println("======================================");
Serial.println("Nachfuehrung beendet.");
nextAction = ACTION_2;
}
else if (nextAction == ACTION_2) {
nextAction = ACTION_ON;
}
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
double Thermister(float RawADC) { //Funktion zur Temperaturbestimmung
double Temp;
Temp = log(((10240000/RawADC) - 10000));
Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
Temp = Temp - 273.15; //Wert in Celsius konvertieren
return Temp;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void rotate(float velo, long GoToStep) { //Funktion zur Steuerung des Motors
if (rotatecounter == 0) { //einmaliger Ablauf vor Aktion
digitalWrite(mstop, HIGH); //Motorsteuerung ein
counted = false;
rotatecounter = 1;
if (GoToStep <= steps) {
rotatevelo = -1 * velo;
}
else {
rotatevelo = velo;
}
}
if (rotatevelo < 0.0) { //Bedingung fuer negative Rotation
if (GoToStep <= steps) {
stepper.setSpeed(rotatevelo);
stepper.runSpeed();
}
else {
counted = true;
}
}
else if (rotatevelo > 0.0) { //Bedingung fuer positive Rotation
if (GoToStep >= steps) {
stepper.setSpeed(rotatevelo);
stepper.runSpeed();
}
else {
counted = true;
}
}
if (counted == true) { //Aktionen nach Steuerung
digitalWrite(mstop, LOW); //Motorsteuerung aus
rotatecounter = 0;
if(status == 1) {
status = 2;
Serial.println("Startstellung angefahren.");
}
else if (status == 6) {
status = 0;
i = 4;
Serial.println("Standbyestellung angefahren.");
}
else if(status == 4) {
myDoubleClickFunction();
}
}
}