// BEGIN TEST
#include <Keypad.h>
const uint8_t ROWS = 4;
const uint8_t COLS = 4;
char keys[ROWS][COLS] = {
{ '1', '2', '3', 'A' },
{ '4', '5', '6', 'B' },
{ '7', '8', '9', 'C' },
{ '*', '0', '#', 'D' }
};
uint8_t colPins[COLS] = { 5, 4, 3 }; // Pins connected to C1, C2, C3
uint8_t rowPins[ROWS] = { 9, 8, 7, 6 }; // Pins connected to R1, R2, R3, R4
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
#include <U8glib.h>
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI
// END TEST
/*
38400 baud
Arduino Nano
ATmega328P (Old Bootloader)
AVRISP mkII programmer
*/
#include <NmraDcc.h>
NmraDcc Dcc;
// Interrupt 0 ist Digital Pin 2 (DCC Input)
int P_DCCIn = 2;
int P_LAAuf = A5; // Aufzug rauf
int P_LAAb = A4; // Aufzug runter
int P_PosIn = A2; // Ebenen-Sensor, analog, max 1023
int RRPosIn = -1; // rocrail Positionsanfrage (1-16)
short LAPos = -1; // aktuelle LA Position (1-16)
short LADir = 0; // 1 aufw, 0 steht, -1 abw
short LASyncT = 2 * 5000; // Zeit in ms-Sekunden die LA rauf / runter fährt in Sync-Phase und auf ein P_PosIn wartet
short posTab[16][4] = {
{200, 100, 1013, 0}, // 1
{200, 100, 998, 0},
{200, 100, 984, 0},
{200, 100, 970, 0},
{200, 100, 955, 0}, // 5
{200, 100, 931, 0},
{200, 100, 908, 0},
{200, 100, 886, 0},
{200, 100, 851, 0},
{200, 100, 818, 0}, // 10
{200, 100, 777, 0},
{200, 100, 738, 0},
{200, 100, 696, 0},
{200, 100, 654, 0},
{200, 100, 596, 0}, // 15
{200, 100, 535, 0}, // 16: Verzögerung von unten, oben, ADC-Wert, cycleCounter
};
boolean isError = false;
boolean doLogDebug = true;
unsigned long uptime;
unsigned long cycle = 0;
boolean syncActive = true;
unsigned long startSyncT;
boolean isReady = false;
void setup() {
// BEGIN TEST
u8g.setFont(u8g_font_gdr25);
u8g.setColorIndex(1);
// END TEST
Serial.begin(38400);
log("Setup ...");
pinMode(P_PosIn, INPUT);
Dcc.pin(P_DCCIn, 0);
Dcc.init(MAN_ID_DIY, 10, CV29_ACCESSORY_DECODER | CV29_OUTPUT_ADDRESS_MODE, 0);
log("Setup done");
startSyncT = millis();
LADir = 1;
log("LAauf, Sync sucht aufwärts");
}
void notifyDccAccTurnoutOutput(uint16_t Addr, uint8_t Direction, uint8_t OutputPower) {
// Addr = (RR_Addr - 1) * 4 + Port
// => Ebene 1 = (13 - 1) * 4 + 1 = 48
RRPosIn = Addr - 48;
log("Gewünschte Ebene: ", RRPosIn);
}
void loop() {
uptime = millis();
//Dcc.process();
// BEGIN TEST
char key = keypad.getKey();
if (key != NO_KEY) {
String t = "";
t += key;
RRPosIn = t.toInt();
log("Gewünschte Ebene: ", RRPosIn);
}
u8g.firstPage();
String x = String(analogRead(P_PosIn));
do {
u8g.drawStr(25, 25, x.c_str());
} while (u8g.nextPage());
// END TEST
if (isError) {
} else {
if (syncActive) {
unsigned long passed = uptime - startSyncT;
//logd("passed: ", passed);
boolean timeIsOver = passed > LASyncT;
/*
// TODO remove statement (implement it in main logic instead)
LAPos = leadingPosIn();
// TODO remove if
if(passed > 100){
int px = analogRead(P_PosIn);
for(byte e=1; e<=16; e++){
if(posTab[e-1][2] > px-3 && posTab[e-1][2] < px+3){
LAPos = e;
}
}
Serial.print("PosIn: ");
Serial.print(px);
if(LAPos != -1){
Serial.print(", LAPos: ");
Serial.println(LAPos);
}else{
Serial.println();
}
LAPos = -1;
startSyncT = uptime;
}
return;
*/
if (timeIsOver) {
if (LADir == 1) {
LADir = -1;
timeIsOver = false;
startSyncT = millis();
LAab();
log("LAab, Sync sucht abwärts");
} else {
syncActive = false;
isError = true;
LAstop(LADir, LAPos);
log("ERROR: LA Sync hat keine Position gefunden.");
}
} else {
if (LADir == 1) {
LAauf();
}
LAPos = leadingPosIn();
if(LAPos > 0){
syncActive = false;
LAstop(LADir, LAPos);
log("LA Sync hat Position gefunden: ", LAPos);
isReady = true;
}
/*
int px = analogRead(P_PosIn);
logd("PosIn: ", px);
if (px >= 100) { // skip floating analog in
LAPos = findPos(px);
// TODO test LAPos != -1
syncActive = false;
LAstop(LADir, LAPos);
log("PosIn: ", px);
log("LA Sync hat Position gefunden: ", LAPos);
isReady = true;
}
*/
}
} else if (isReady) {
if (RRPosIn != -1) {
/*
int px = analogRead(P_PosIn);
log("PosIn: ", px);
LAPos = findPos(px);
*/
LAPos = leadingPosIn();
if(LAPos > 0){
// TODO matchen RRPos und LAPos? LAPos=16 == RRPos=16 oder RRPos=1?
if (RRPosIn < LAPos) {
log("Position erkannt: ", LAPos);
log("LAauf, Richtung: ", RRPosIn);
LAauf();
} else if (RRPosIn > LAPos) {
log("Position erkannt: ", LAPos);
log("LAab, Richtung: ", RRPosIn);
LAab();
} else {
LAstop(LADir, LAPos);
log("LA hat Position gefunden: ", LAPos);
RRPosIn = -1;
}
}
}
}
}
}
void LAauf() {
analogWrite(P_LAAb, 0);
analogWrite(P_LAAuf, 255);
}
void LAab() {
analogWrite(P_LAAb, 255);
analogWrite(P_LAAuf, 0);
}
void LAstop(short dir, short pos) {
short posDelay = 0;
if (dir == 1 && pos > 0) {
posDelay = posTab[pos - 1][1];
} else if (dir == -1 && pos > 0) {
posDelay = posTab[pos - 1][0];
}
log("Stop auf Position: ", pos);
log("Verzögerung: ", posDelay);
delay(posDelay);
analogWrite(P_LAAuf, 0);
analogWrite(P_LAAb, 0);
}
short findPos(int px){
if(px > 100){ // skip floating analog in
for(byte e=1; e<=16; e++){
if(posTab[e-1][2] > px-3 && posTab[e-1][2] < px+3){
return e;
}
}
}
return -1;
}
// returns 0=collecting, -1=no leading position found, >=1=found position nr
short leadingPosIn(){
if(++cycle < 100){
// collect values
int px = analogRead(P_PosIn) + random(1, 10);
//logd("PosIn: ", px);
int cycleLAPos = findPos(px);
bool posFound = cycleLAPos > -1;
if(posFound){
//logd("pos: ", cycleLAPos);
posTab[cycleLAPos-1][3] += 1;
}
return 0;
}else{
// find position with highest counter value
short mostFoundPos = -1;
byte maxCount = 0;
for(byte e=1; e<=16; e++){
if(posTab[e-1][3] > maxCount){
maxCount = posTab[e-1][3];
mostFoundPos = e;
//logd("leading pos: ", mostFoundPos);
}
}
// reset counters
for(byte e=1; e<=16; e++){
//logd("pos: ", e);
//logd("count: ", posTab[e-1][3]);
posTab[e-1][3] = 0;
}
cycle = 0;
return mostFoundPos;
}
}
void logd(char a[]) {
logd(a, -333);
}
void logd(char a[], int b) {
if (!doLogDebug) return;
if (sizeof(b) > 0 && b != -333) {
Serial.print(a);
Serial.println(b);
} else {
Serial.println(a);
}
}
void log(char a[]) {
log(a, -333);
}
void log(char a[], int b) {
if (sizeof(b) > 0 && b != -333) {
Serial.print(a);
Serial.println(b);
} else {
Serial.println(a);
}
}