/*
*
* Arduinowindensteuerung Aws
*
*/
#include <Arduino.h>
#include <EEPROM.h>
#include <Wire.h>
#include "Aws.h"
#include "AwsPins.h"
#include "AwsHandle.h"
#include "AwsLCD.h"
#include "AwsRamp.h"
#include "AwsRotaryAdapter.h"
#include "AwsEEPROM.h"
// Global state Variables
/*
* The selected program
*/
int8_t program = 0;
/*
* Data of program from EEPROM (modifiable by EDITNAME, EDITSPEED, EDITWEIGHT)
*/
planedata selectedPlane;
/*
* Lock status of selected program. Lock required before using the Joystick
*/
boolean locked = false;
/*
* The selected wind speed
*/
int8_t wind = 0;
/*
* The state of the Joystick
* values are STATE_RESET, STATE_MANUAL, STATE_START and STATE_ILLEGAL
*/
uint8_t state = STATE_RESET;
/*
* editMode describes the action that can be performed with the rotary encoders
* values are NOEDIT, EDITNAME, EDITSPEED, EDITWEIGHT, EDITSAVE
*/
uint8_t editMode = NOEDIT;
// Controller for rotary sensors
AwsRotaryAdapter rotary(&selectedPlane);
// Ramp Controller
AwsRamp ramp;
// LCD Controller
AwsLCD awsLcd;
// Start-Stop Controler
AwsHandle handle;
/**
* Initialize hardware
* Executed once after boot
*/
static int startC=START_CONSTANTS;
static int planecnt=0;
void sc(int16_t value){
EEPROM.put(startC,value);
startC+=sizeof(value);
}
void sp(char* name, int16_t speed, int16_t weight){
planedata plane;
plane.speed=speed;
plane.weight=weight;
memcpy(plane.name,name,DISPLAY_WIDTH);
EEPROM.put(START_PLANES+planecnt*sizeof(planedata),plane);
planecnt++;
}
void spc(){
EEPROM.put(0,(uint8_t)planecnt);
}
void setup() {
// Serial
DEBUG(Serial.begin(9600); Serial.println(F("Start"));)
sp("20 Gruene Post ", 1477 , 1694);
sp("21 Baby ", 1527 , 1794);
sp("30 Ka8 K6 Zugvogel ", 1572 , 2146);
sp("40 LS1 Libelle ", 1857 , 2200);
sp("41 Astir ", 1897 , 2200);
sp("50 LS4 ", 1934 , 2200);
sp("51 Discus 1 ", 1984 , 2314);
sp("52 Discus 2 ", 2034 , 2294);
sp("53 ASW28 ", 2044 , 2314);
sp("60 Discus Wasser ", 2044 , 2798);
sp("70 ASK13 einsitzig ", 1668 , 2286);
sp("80 ASK13 zweisitzig ", 1772 , 2449);
sp("90 ASK21 ", 1927 , 2894);
sp("99 Duo Discus ", 2142 , 2940);
spc();
sc(10);sc(14);sc(16);sc(25);
sc(27);sc(-15);sc(40);sc(12);
sc(24);sc(37);sc(49);sc(61);
sc(73);sc(86);sc(98);sc(110);
sc(122);sc(135);sc(147);sc(159);
sc(172);sc(184);sc(196);sc(208);
sc(220);sc(233);sc(245);sc(257);
sc(269);sc(282);sc(294);sc(306);
//LOCK, Buzzer and LED
pinMode(LOCKPIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
pinMode(Buzzer_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
digitalWrite(Buzzer_PIN, LOW);
awsLcd.lcdInit();
rotary.init();
handle.init();
DEBUG(Serial.println(F("Setup finished"));)
}
/**
* aliveMessage for DEBUG only
*/
void aliveMessage() {
DEBUG(long seconds = millis() / 15000;
ONCHANGE(seconds, Serial.println(F("alive"));))
}
/**
* show or hide Voltages incl wind and ramp reduction on demand
*/
void updateVoltagesDisplay() {
boolean displayVolts = rotary.displayVoltage();
#if DISPLAY_WIDTH == 16
static char *voltageHeader = (char *)"Ges La";
#else
static char *voltageHeader = (char *)"Gesch Last";
#endif
ONCHANGE(
displayVolts,
if (displayVolts) { awsLcd.showMessage(voltageHeader, 1, 0, 1); } else {
awsLcd.updateLCDSpeed(0);
awsLcd.updateLCDWeight(0);
awsLcd.showMessage((char *)" ", 1, 0, 1);
})
if (displayVolts) {
int16_t effectiveSpeed =
selectedPlane.speed - (editMode == NOEDIT ? WIND_FACTOR * wind : 0);
awsLcd.updateLCDSpeed(effectiveSpeed > 0 ? (uint16_t)effectiveSpeed : 0);
int16_t reducedWeight = selectedPlane.weight -
(editMode == NOEDIT ? ramp.getRampReduction() : 0);
awsLcd.updateLCDWeight(reducedWeight > 0 ? (uint16_t)reducedWeight : 0);
}
}
/**
* updateLockDisplay aktualisiert die Anzeige der
* LED und des Lock Symbols im LCD Display
*/
void updateLockDisplay() {
// Set locked marker in lcd display and LED
ONCHANGE(
locked,
if (locked) {
awsLcd.showMessage((char *)"L", 0, DISPLAY_WIDTH - 1, 0);
digitalWrite(LED_PIN, LOW);
ramp.init(wind, selectedPlane);
} else {
awsLcd.showMessage((char *)" ", 0, DISPLAY_WIDTH - 1, 0);
digitalWrite(LED_PIN, HIGH);
ramp.stop();
})
}
/**
* updateRamp aktualisiert den Zustand der Rampe
* und startet oder stoppt die Rampe
* je nach Zustand
*/
void updateRamp() {
// things to be done once on change
ONCHANGE(
state,
DEBUG(Serial.print(F("Handle state changed to "));
Serial.println(state);) if (state == STATE_RESET) {
rotary.enable();
if (ramp.isRunning()) awsLcd.unToggleProgressIndicator();
ramp.stop();
digitalWrite(Buzzer_PIN, LOW);
if (locked) {
ramp.init(wind, selectedPlane);
}
} else {
rotary.disable();
if (locked && !ramp.isRunning()) {
ramp.prepareStart();
}
if ((!locked) || state == STATE_ILLEGAL) {
digitalWrite(Buzzer_PIN, HIGH);
DEBUG(char buf[16]; snprintf(buf, sizeof(buf), "%s %d",
locked ? "locked" : "unlocked", state);
Serial.println(buf);)
}
}) // END ONCHANGE STATE
if (ramp.isRunning()) { // if ramp not stopped State must be MANUAL and not
// RESET keep on truning progress indicator, ramp
// may be resumed
awsLcd.toggleProgressIndicator();
}
if ((state == STATE_START) && locked) {
ramp.run();
}
}
/**
*
* mainMenu
*
* Main Menu to Control UI using rotary sensors
*
*/
void mainMenu() {
aliveMessage();
ONCHANGE(
editMode, DEBUG(Serial.print("editMode Changed");
Serial.println(editMode);) switch (editMode) {
case NOEDIT:
switch (rotary.terminateEditMode()) {
case EDITINSERT:
insertPlaneIntoEEPROM(program, selectedPlane);
rotary.init(); //numPlanes changed
break;
case EDITSAVE:
storePlaneInEEPROM(program, selectedPlane);
break;
case EDITDELETE:
deletePlaneFromEEPROM(program);
rotary.init(); //numPlanes changed
default:
break;
};
awsLcd.showMessage((char *)" ", 0, DISPLAY_WIDTH - 1, 0);
break;
case EDITNAME:
awsLcd.showMessage((char *)"1", 0, DISPLAY_WIDTH - 1, 0);
updateVoltagesDisplay(); // No Wind component required
break;
case EDITSPEED:
awsLcd.showMessage((char *)"2", 0, DISPLAY_WIDTH - 1, 0);
awsLcd.blink(1, 0);
break;
case EDITWEIGHT:
awsLcd.showMessage((char *)"3", 0, DISPLAY_WIDTH - 1, 0);
awsLcd.blink(1, 8);
break;
case EDITSAVE:
awsLcd.noblink();
awsLcd.showMessage((char *)"S", 0, DISPLAY_WIDTH - 1, 0);
awsLcd.showMessage((char *)"SAVE? ", 0, 0, 1);
break;
case EDITINSERT:
awsLcd.showMessage((char *)"INSERT? ", 0, 0, 1);
break;
case EDITDELETE:
awsLcd.showMessage((char *)"DELETE? ", 0, 0, 1);
break;
case EDITCANCEL:
awsLcd.showMessage((char *)"CANCEL? ", 0, 0, 1);
break;
})
switch (editMode) {
case NOEDIT: {
ONCHANGE(program, getPlaneFromEEPROM(program, selectedPlane);
char line[DISPLAY_WIDTH + 1]; line[DISPLAY_WIDTH] = 0x00;
strncpy(line, selectedPlane.name, DISPLAY_WIDTH);
awsLcd.showMessage(line, 0, 0, 1);)
// LCD Update only if Changes happened
updateVoltagesDisplay();
awsLcd.updateLCDWind(wind);
updateLockDisplay();
updateRamp();
} break;
case EDITNAME: {
int8_t editPos = rotary.getEditPos();
int16_t hash = 0;
for (uint8_t i = 0; i < sizeof(selectedPlane.name); i++)
hash += selectedPlane.name[i];
ONCHANGE(hash, char line[DISPLAY_WIDTH + 1]; line[DISPLAY_WIDTH] = 0x00;
strncpy(line, selectedPlane.name, DISPLAY_WIDTH);
awsLcd.showMessage(line, 0, 0, 1);
awsLcd.blink(0, editPos);) // END ONCHANGE hash
ONCHANGE(editPos, awsLcd.blink(0, editPos);)
} break;
case EDITSPEED:
awsLcd.blink(1, 0);
updateVoltagesDisplay();
break;
case EDITWEIGHT:
awsLcd.blink(1, 9);
updateVoltagesDisplay();
break;
case EDITSAVE:
break;
}
}
void computeNewState() {
rotary.update(); // Poll rotary sensors and store status
program = rotary.getProgram();
locked = rotary.isLocked();
wind = rotary.getWind();
state = handle.getState();
editMode = rotary.editMode();
}
void loop() {
computeNewState();
mainMenu();
}
Edit Lock
Reset
Start
Buzzer Alarm
Programm Sperre
Rot: Kein Start möglich, Programmwahl möglich
Grün: Start möglich, Programmwahl und Windkomponente gesperrt.
Programmanzeige
Windanzeige
Drehregler
Programmwahl
Drehregler
Windkomponente
Bedienungsanleitung
1) Mit Drehregler Programmwahl den Flugzeugtyp einstellen.
2) Mit Drehregler Windkomponente diese einstellen.
3) Sperren der Einstellungen durch Druck auf Drehregler Programmwahl. L (Lock) deutet die Sperre an.
Grüne LED leuchtet.
4) Schieberegler Reset nach rechts.
5) Schieberegler Start rechts.
6) Aktivitätsanzeiger in der Programmanzeige läuft.
Die Spannungsvorgaben werden in der Ausgabe angezeigt.
7) Schieberegler Start auf Ausgangsposition (links).
8) Schieberegler Reset auf Ausgangsposition (links).
9) Sperre durch Druck auf Programmwahlregler aufheben.
L verschwindet und rote LED leuchtet.