From 349d1d644e38b6b2175eb2247ba342abda7e03b2 Mon Sep 17 00:00:00 2001 From: Andi Date: Sun, 14 May 2023 21:22:04 +0200 Subject: [PATCH] Pendelzug Erstversion new file: .gitignore new file: .vscode/extensions.json new file: ErsterTest.code-workspace new file: include/README new file: lib/AnalogFiveButtons/AnalogFiveButtons.cpp new file: lib/AnalogFiveButtons/AnalogFiveButtons.h new file: lib/Imotor/Imotor.cpp new file: lib/Imotor/Imotor.h new file: lib/L298n/L298n.cpp new file: lib/L298n/L298n.h new file: lib/README new file: lib/fahrt/fahrt.cpp new file: lib/fahrt/fahrt.h new file: lib/gleis/gleis.cpp new file: lib/gleis/gleis.h new file: lib/gleisabschnitt/gleisabschnitt.cpp new file: lib/gleisabschnitt/gleisabschnitt.h new file: lib/locomotive/locomotive.cpp new file: lib/locomotive/locomotive.h new file: lib/motor/dfquad.h new file: lib/motor/motor.cpp new file: lib/motor/motor.h new file: lib/weiche/weiche.cpp new file: lib/weiche/weiche.h new file: platformio.ini new file: src/main.cpp new file: test/README --- .gitignore | 5 + .vscode/extensions.json | 10 ++ ErsterTest.code-workspace | 12 ++ include/README | 39 ++++++ lib/AnalogFiveButtons/AnalogFiveButtons.cpp | 123 +++++++++++++++++ lib/AnalogFiveButtons/AnalogFiveButtons.h | 64 +++++++++ lib/Imotor/Imotor.cpp | 25 ++++ lib/Imotor/Imotor.h | 21 +++ lib/L298n/L298n.cpp | 61 +++++++++ lib/L298n/L298n.h | 22 ++++ lib/README | 46 +++++++ lib/fahrt/fahrt.cpp | 77 +++++++++++ lib/fahrt/fahrt.h | 33 +++++ lib/gleis/gleis.cpp | 14 ++ lib/gleis/gleis.h | 22 ++++ lib/gleisabschnitt/gleisabschnitt.cpp | 14 ++ lib/gleisabschnitt/gleisabschnitt.h | 17 +++ lib/locomotive/locomotive.cpp | 119 +++++++++++++++++ lib/locomotive/locomotive.h | 36 +++++ lib/motor/dfquad.h | 7 + lib/motor/motor.cpp | 47 +++++++ lib/motor/motor.h | 22 ++++ lib/weiche/weiche.cpp | 26 ++++ lib/weiche/weiche.h | 21 +++ platformio.ini | 18 +++ src/main.cpp | 139 ++++++++++++++++++++ test/README | 11 ++ 27 files changed, 1051 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 ErsterTest.code-workspace create mode 100644 include/README create mode 100644 lib/AnalogFiveButtons/AnalogFiveButtons.cpp create mode 100644 lib/AnalogFiveButtons/AnalogFiveButtons.h create mode 100644 lib/Imotor/Imotor.cpp create mode 100644 lib/Imotor/Imotor.h create mode 100644 lib/L298n/L298n.cpp create mode 100644 lib/L298n/L298n.h create mode 100644 lib/README create mode 100644 lib/fahrt/fahrt.cpp create mode 100644 lib/fahrt/fahrt.h create mode 100644 lib/gleis/gleis.cpp create mode 100644 lib/gleis/gleis.h create mode 100644 lib/gleisabschnitt/gleisabschnitt.cpp create mode 100644 lib/gleisabschnitt/gleisabschnitt.h create mode 100644 lib/locomotive/locomotive.cpp create mode 100644 lib/locomotive/locomotive.h create mode 100644 lib/motor/dfquad.h create mode 100644 lib/motor/motor.cpp create mode 100644 lib/motor/motor.h create mode 100644 lib/weiche/weiche.cpp create mode 100644 lib/weiche/weiche.h create mode 100644 platformio.ini create mode 100644 src/main.cpp create mode 100644 test/README diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/ErsterTest.code-workspace b/ErsterTest.code-workspace new file mode 100644 index 0000000..37c292b --- /dev/null +++ b/ErsterTest.code-workspace @@ -0,0 +1,12 @@ +{ + "folders": [ + { + "path": "." + }, + { + "name": "IR Remote", + "path": "../IR Remote" + } + ], + "settings": {} +} \ No newline at end of file diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/AnalogFiveButtons/AnalogFiveButtons.cpp b/lib/AnalogFiveButtons/AnalogFiveButtons.cpp new file mode 100644 index 0000000..55dd569 --- /dev/null +++ b/lib/AnalogFiveButtons/AnalogFiveButtons.cpp @@ -0,0 +1,123 @@ +/* + AnalogFiveButtonsDebounce class for the analog 5 keys panels + Version 1.0 + + Copyright (c) 2015 - Kiss Gábor (kiss-gabor@outlook.hu) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. +*/ + + +#include +#include +#include "AnalogFiveButtons.h" + + +#define DEFAULT_FAILURE_RATE 10 + + + +// analogPin : where is the keypad OUT pin connected (A0, A1..) +// typeOfModule: 0-red Keyes_AD_Key module, 1-LCD Keypad module +AnalogFiveButtonsDebounce::AnalogFiveButtonsDebounce(uint8_t analogPin, uint8_t typeOfModule) +{ + if(typeOfModule == KEYES_AD_KEY) { + + // Default values for the Keyes_AD_Key module + // Parameters: analog pin, failure rate, left, up, down, right, fire + init( analogPin, DEFAULT_FAILURE_RATE, 0, 140, 320, 500, 740); + + } else if(typeOfModule == LCD_KEYPAD) { + + // Default values for the LCD Keypad module + // Parameters: analog pin, failure rate, left, up, down, right, fire + init( analogPin, DEFAULT_FAILURE_RATE, 480, 130, 305, 0, 720); + } +} + + + +// Custom defined module +// Parameters: analogue pin, failure rate, left, up, down, right, fire values +AnalogFiveButtonsDebounce::AnalogFiveButtonsDebounce(uint8_t analogPin, uint8_t failureRate, int sw1Value, int sw2Value, int sw3Value, int sw4Value, int sw5Value) +{ + init(analogPin, failureRate, sw1Value, sw2Value, sw3Value, sw4Value, sw5Value); +} + + + +void AnalogFiveButtonsDebounce::init(uint8_t analogPin, uint8_t failureRate, int sw1Value, int sw2Value, int sw3Value, int sw4Value, int sw5Value) +{ + analogReference(DEFAULT); + + _analogPin = analogPin; + _failureRate = failureRate; + _sw1Value = sw1Value; + _sw2Value = sw2Value; + _sw3Value = sw3Value; + _sw4Value = sw4Value; + _sw5Value = sw5Value; + sensorValue = 0; + oldKey = 1; + newKey = 0; + lastflickerablekey = 0; +} + + +void AnalogFiveButtonsDebounce::evalButton() +{ + // Key reset + newKey = SW_NO_PUSH; + + sensorValue = analogRead(_analogPin); + + if( (sensorValue > (_sw5Value - _failureRate)) && (sensorValue < (_sw5Value + _failureRate)) ) newKey = 5; // Fire + if( (sensorValue > (_sw4Value - _failureRate)) && (sensorValue < (_sw4Value + _failureRate)) ) newKey = 4; // Right + if( (sensorValue > (_sw3Value - _failureRate)) && (sensorValue < (_sw3Value + _failureRate)) ) newKey = 3; // Down + if( (sensorValue > (_sw2Value - _failureRate)) && (sensorValue < (_sw2Value + _failureRate)) ) newKey = 2; // Up + if( (sensorValue > (_sw1Value - _failureRate)) && (sensorValue < (_sw1Value + _failureRate)) ) newKey = 1; // Left +} + + +uint8_t AnalogFiveButtonsDebounce::getButton() +{ + evalButton(); + + return newKey; +} + + +uint8_t AnalogFiveButtonsDebounce::changedButton() +{ + evalButton(); + + if( newKey != lastflickerablekey) { + lastdebouncetime = millis(); + lastflickerablekey = newKey; + newKey = SW_NO_CHANGE; + } + + if((millis() - lastdebouncetime) > DEBOUNCEDELAY) { + + if(oldKey == newKey) + { + // Nothing is changed + newKey = SW_NO_CHANGE; + } else { + oldKey = newKey; + } + } + else { + newKey = SW_NO_CHANGE; + } + + return newKey; +} diff --git a/lib/AnalogFiveButtons/AnalogFiveButtons.h b/lib/AnalogFiveButtons/AnalogFiveButtons.h new file mode 100644 index 0000000..e8aa1c8 --- /dev/null +++ b/lib/AnalogFiveButtons/AnalogFiveButtons.h @@ -0,0 +1,64 @@ +// ensure this library description is only included once +#ifndef A5Bdb_h +#define A5Bdb_h + +#include + +#define SW1 1 +#define SW2 2 +#define SW3 3 +#define SW4 4 +#define SW5 5 +#define SW_NO_PUSH 0 +#define SW_NO_CHANGE 255 + +#define BTN_LEFT 1 +#define BTN_UP 2 +#define BTN_DOWN 3 +#define BTN_RIGHT 4 +#define BTN_FIRE 5 +#define BTN_SELECT 5 +#define BTN_NO_PUSH 0 +#define BTN_NO_CHANGE 255 + + +// Module selection +#define KEYES_AD_KEY 0 +#define LCD_KEYPAD 1 + + +class AnalogFiveButtonsDebounce +{ + public: + // analogPin : where is the keypad analog pin is connected (A0, A1..) + // typeOfModule: 0-red Keyes_AD_Key module, 1-LCD Keypad module + AnalogFiveButtonsDebounce(uint8_t , uint8_t ); + // Custom defined module + // Parameters: analogue pin, failure rate, left value, up value, down value, right value, fire value + AnalogFiveButtonsDebounce(uint8_t , uint8_t , int , int , int , int , int ); + // Returns: - actually pressed key (1-5) + // - 0 if no key is pressed + uint8_t getButton(); + // Returns: - the changed key (1-5) + // - 0 if no key is pressed + // - 255 if nothing is changed + uint8_t changedButton(); + + private: + // Values of buttons + int _sw1Value, _sw2Value, _sw3Value, _sw4Value, _sw5Value; + // The analog pin number (A0, A1...) + uint8_t _analogPin; + // Failure Rate, default 10 + uint8_t _failureRate; + // Analog port value + int sensorValue; + uint8_t oldKey, newKey, lastflickerablekey; + unsigned long lastdebouncetime; + const uint8_t DEBOUNCEDELAY=50; + void init(uint8_t , uint8_t , int , int , int , int , int ); + void evalButton(); + +}; + +#endif diff --git a/lib/Imotor/Imotor.cpp b/lib/Imotor/Imotor.cpp new file mode 100644 index 0000000..88bd16b --- /dev/null +++ b/lib/Imotor/Imotor.cpp @@ -0,0 +1,25 @@ +#include "Imotor.h" +#include "Arduino.h" + +IMotor::IMotor() + { + + } +/* +void IMotor::setSpeed(int speed) + { + setDirection (_currentDir); + analogWrite(_pinPwm, speed); + } + +void IMotor::setDirection(MotorDirection dir) + { + _currentDir=dir; + Serial.println("oje"); + } + +void IMotor::Stop() + { + setSpeed (0); + } +*/ diff --git a/lib/Imotor/Imotor.h b/lib/Imotor/Imotor.h new file mode 100644 index 0000000..b22fbc6 --- /dev/null +++ b/lib/Imotor/Imotor.h @@ -0,0 +1,21 @@ +#ifndef IMotor_h +#define IMotor_h + +#include "Arduino.h" + +enum MotorDirection {motorForward, motorBackward}; + +class IMotor +{ + public: + IMotor(); + virtual void setSpeed(int speed) = 0; + virtual void setDirection(MotorDirection dir) = 0; + virtual void Stop() = 0; + + protected: + byte _pinPwm; + MotorDirection _currentDir; +}; + +#endif \ No newline at end of file diff --git a/lib/L298n/L298n.cpp b/lib/L298n/L298n.cpp new file mode 100644 index 0000000..7e5cb13 --- /dev/null +++ b/lib/L298n/L298n.cpp @@ -0,0 +1,61 @@ +#include "IMotor.h" +#include +#include "Arduino.h" + + + L298n::L298n(int pinPwm, int pin1, int pin2) + { + _pinPwm = pinPwm; + _pin1 = pin1; + _pin2 = pin2; + _currentDir = motorForward; + + pinMode(_pinPwm,OUTPUT); + pinMode(_pin1,OUTPUT); + pinMode(_pin2,OUTPUT); + digitalWrite(_pin1, LOW); + digitalWrite(_pin2, LOW); + + } + + void L298n::setSpeed(int speed) + { +/* Serial.print("Regler Speed:" ); + Serial.print(speed); + Serial.print(" on "); + Serial.println(_pinPwm); */ + analogWrite(_pinPwm, speed); + setDirection(_currentDir); + + } + + void L298n::setDirection(MotorDirection dir) + { + _currentDir=dir; + if (_currentDir == motorBackward) + { +/* Serial.print("Regler backward"); + Serial.print(_pin1); + Serial.print("-"); + Serial.println(_pin2); */ + digitalWrite(_pin2, LOW); + digitalWrite(_pin1, HIGH); + } + else + { +/* Serial.print("Regler forward"); + Serial.print(_pin1); + Serial.print("-"); + Serial.println(_pin2); */ + digitalWrite(_pin1, LOW); + digitalWrite(_pin2, HIGH); + } + } + + void L298n::Stop() + { + digitalWrite(_pin1, LOW); + digitalWrite(_pin2, LOW); + setSpeed (0); + } + diff --git a/lib/L298n/L298n.h b/lib/L298n/L298n.h new file mode 100644 index 0000000..13e7ba8 --- /dev/null +++ b/lib/L298n/L298n.h @@ -0,0 +1,22 @@ +#ifndef L298_h +#define L298_h + +#include "Arduino.h" +#include + +class L298n : public IMotor +{ + public: + L298n(int pinPwm, int pin1, int pin2); + virtual void setSpeed(int speed) override; + virtual void setDirection(MotorDirection dir) override; + virtual void Stop() override; + + private: + int _pin1; + int _pin2; + +}; + + +#endif \ No newline at end of file diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/lib/fahrt/fahrt.cpp b/lib/fahrt/fahrt.cpp new file mode 100644 index 0000000..7ae7264 --- /dev/null +++ b/lib/fahrt/fahrt.cpp @@ -0,0 +1,77 @@ +# include +#include +#include + +Fahrt::Fahrt(Locomotive locomotive, MotorDirection Direction, Gleis gleis, Gleisabschnitt gleisabschnitt): _locomotive(locomotive), _gleis(gleis), _gleisabschnitt(gleisabschnitt) +{ + _direction = Direction; + _speed = locomotive.getDefaultSpeed(); + _bremsweg=0; +} + +Fahrt::Fahrt(Locomotive locomotive, byte speed, MotorDirection Direction, Gleis gleis, Gleisabschnitt gleisabschnitt): _locomotive(locomotive), _gleis(gleis), _gleisabschnitt(gleisabschnitt) +{ + _direction = Direction; + _speed = speed; + _bremsweg=0; +} + +Fahrt::Fahrt(Locomotive locomotive, byte speed, MotorDirection Direction, Gleis gleis, Gleisabschnitt gleisabschnitt, float bremsweg): _locomotive(locomotive), _gleis(gleis), _gleisabschnitt(gleisabschnitt) +{ + _direction = Direction; + _speed = speed; + _bremsweg=bremsweg; +} + + +void Fahrt::Vorbereiten() +{ + _gleis.Waehlen(); + _abschnittErkannt=false; + Serial.print ("Auftrag: Speed="); + Serial.print (_speed); + Serial.print (" Bremsweg="); + Serial.print (_bremsweg); + Serial.println(); +} + +void Fahrt::Start() +{ + _locomotive.setDirection(_direction); + _locomotive.Accelerate(_speed); +} + +void Fahrt::Loop() +{ + _locomotive.loop(); + if (_gleisabschnitt.IstBesetzt() && !_abschnittErkannt) + { + + delay(20); + if (_gleisabschnitt.IstBesetzt() && !_abschnittErkannt) + { + if (_bremsweg==0) + _locomotive.Break(); + else + _locomotive.Accelerate(0, _bremsweg); + _abschnittErkannt=true; + } + } +} + +bool Fahrt::IstAngekommen() +{ + return (_locomotive.currentSpeed()==0); +} + +float Fahrt::ChangeBremsweg(float DeltaBremsweg) +{ + _bremsweg += DeltaBremsweg; + return(_bremsweg); +} + +byte Fahrt::ChangeSpeed(byte DeltaSpeed) +{ + _speed += DeltaSpeed; + return(_speed); +} diff --git a/lib/fahrt/fahrt.h b/lib/fahrt/fahrt.h new file mode 100644 index 0000000..00bfdde --- /dev/null +++ b/lib/fahrt/fahrt.h @@ -0,0 +1,33 @@ +#ifndef Fahrt_h +#define Fahrt_h + +#include +#include +#include + +class Fahrt +{ + public: + Fahrt(Locomotive locomotive, MotorDirection Direction, Gleis gleis, Gleisabschnitt gleisabschnitt); + Fahrt(Locomotive locomotive, byte speed, MotorDirection Direction, Gleis gleis, Gleisabschnitt gleisabschnitt); + Fahrt(Locomotive locomotive, byte speed, MotorDirection Direction, Gleis gleis, Gleisabschnitt gleisabschnitt, float bremsweg); + void Vorbereiten(); + void Start(); + void Loop(); + bool IstAngekommen(); + + float ChangeBremsweg(float DeltaBremsweg); + byte ChangeSpeed(byte DeltaSpeed); + + + private: + Locomotive _locomotive; + MotorDirection _direction; + Gleis _gleis; + Gleisabschnitt _gleisabschnitt; + bool _abschnittErkannt; + byte _speed; + float _bremsweg; +}; + +#endif \ No newline at end of file diff --git a/lib/gleis/gleis.cpp b/lib/gleis/gleis.cpp new file mode 100644 index 0000000..fd88fe6 --- /dev/null +++ b/lib/gleis/gleis.cpp @@ -0,0 +1,14 @@ +#include +#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember)) + + +Gleis::Gleis(Weiche weiche, Weiche::WeicheSchalten weicheSchalten): _weiche (weiche), _weicheSchalten(weicheSchalten) +{ + _keineWeiche = false; +} + +void Gleis::Waehlen() +{ + if (!_keineWeiche) + CALL_MEMBER_FN(_weiche, _weicheSchalten)(); +} diff --git a/lib/gleis/gleis.h b/lib/gleis/gleis.h new file mode 100644 index 0000000..f2954b1 --- /dev/null +++ b/lib/gleis/gleis.h @@ -0,0 +1,22 @@ +#ifndef Gleis_h +#define Gleis_h + +#include "Arduino.h" +#include +#include +#include + +class Gleis +{ + public: + Gleis(); + Gleis(Weiche weiche, Weiche::WeicheSchalten weicheSchalten); + void Waehlen(); + + private: + Weiche _weiche; + Weiche::WeicheSchalten _weicheSchalten; + bool _keineWeiche; +}; + +#endif diff --git a/lib/gleisabschnitt/gleisabschnitt.cpp b/lib/gleisabschnitt/gleisabschnitt.cpp new file mode 100644 index 0000000..341e8d2 --- /dev/null +++ b/lib/gleisabschnitt/gleisabschnitt.cpp @@ -0,0 +1,14 @@ +#include +#include + + Gleisabschnitt::Gleisabschnitt(int pin) : _pin(pin) + { + pinMode(pin, INPUT_PULLUP); + }; + + bool Gleisabschnitt::IstBesetzt() { + if (digitalRead(_pin)==HIGH) + return false; + else + return true; + }; diff --git a/lib/gleisabschnitt/gleisabschnitt.h b/lib/gleisabschnitt/gleisabschnitt.h new file mode 100644 index 0000000..2100eeb --- /dev/null +++ b/lib/gleisabschnitt/gleisabschnitt.h @@ -0,0 +1,17 @@ +#ifndef Gleisabschnitt_h +#define Gleisabschnitt_h + +#include "Arduino.h" + +class Gleisabschnitt +{ + public: + Gleisabschnitt(int pin); + bool IstBesetzt(); + + private: + int _pin; +}; + + +#endif \ No newline at end of file diff --git a/lib/locomotive/locomotive.cpp b/lib/locomotive/locomotive.cpp new file mode 100644 index 0000000..83c90e4 --- /dev/null +++ b/lib/locomotive/locomotive.cpp @@ -0,0 +1,119 @@ +#include +#include +#include + +Locomotive::Locomotive(int accelerate, int decelerate, byte minSpeed, byte maxSpeed, IMotor& motor): _motor(motor) +{ + _currentSpeed=0; + _currentAcc=0; + _accelerate=accelerate; + _decelerate=decelerate; + _minSpeed=minSpeed; + _maxSpeed=maxSpeed; + +}; + +void Locomotive::Accelerate() +{ + Accelerate(_maxSpeed); +}; + +void Locomotive::Accelerate(byte Speed) +{ +/* Serial.print("Locomotive.Accelerate: "); + Serial.print(_currentSpeed); + Serial.print(" "); + Serial.print(Speed); + Serial.print(" "); +*/ + _targetSpeed = Speed; + _millisStart = millis()-_delay; + if (_targetSpeed>_currentSpeed) + _currentAcc = _accelerate; + else + _currentAcc = - _decelerate; + +}; + + +void Locomotive::Accelerate(byte Speed, float bremsweg) +{ + _targetSpeed = Speed; + _currentSpeed = (_currentSpeed<_minSpeed)? _minSpeed : _currentSpeed; + _millisStart = millis()-_delay; + + byte _targetSpeed2 = ((_targetSpeed < _currentSpeed)&&(_targetSpeed == 0)) ? _minSpeed : _targetSpeed; + int deltaspeed = (_targetSpeed2 - _currentSpeed); + + _currentAcc = copysign(deltaspeed * deltaspeed / (100.0 * bremsweg), deltaspeed); + if (_currentAcc == 0) + _currentAcc = copysign(1, deltaspeed); + +}; + + +void Locomotive::Break() +{ + Accelerate(0); +}; + +void Locomotive::setSpeed(byte Speed) +{ + _currentSpeed = Speed; + _motor.setSpeed(_currentSpeed); +}; + +void Locomotive::setDirection(MotorDirection dir) +{ + Serial.print("Lokomotive Richtung: "); + Serial.println(dir); + _motor.setDirection(dir); +}; + +void Locomotive::loop() +{ + unsigned long currentMillis; + currentMillis = millis(); + if (currentMillis - _millisStart >= _delay) //test whether the period has elapsed + { + byte newspeed; + newspeed = _currentSpeed + _currentAcc; + /* Serial.print("Locomotive.Loop: "); + Serial.print(_currentSpeed); + Serial.print(" "); + Serial.print(_currentAcc); + Serial.print(" "); + Serial.println(newspeed); +*/ + + int breakspeed = _minSpeed * 80 / 100; + + if ((newspeed>_targetSpeed) && (_currentAcc>0)) + { + newspeed = _targetSpeed; + _currentAcc =0; + } + else if ((newspeed<_minSpeed) && (_currentAcc>0)) newspeed = _minSpeed; + else if ((newspeed + +Weiche::Weiche(IMotor& motor): _motor(motor) +{ + +} + +void Weiche::Geradeaus() +{ + _motor.setDirection(motorForward); + _motor.setSpeed(_speed); + Serial.println("geradeaus"); + delay(_delay); + _motor.setSpeed(0); + Serial.println("--"); +} + +void Weiche::Abzweigen() +{ + _motor.setDirection(motorBackward); + _motor.setSpeed(_speed); + Serial.println("abzweigen"); + delay(_delay); + _motor.setSpeed(0); + Serial.println("--"); +} diff --git a/lib/weiche/weiche.h b/lib/weiche/weiche.h new file mode 100644 index 0000000..bc3ad66 --- /dev/null +++ b/lib/weiche/weiche.h @@ -0,0 +1,21 @@ +#ifndef Weiche_h +#define Weiche_h + +# include + + +class Weiche { + public: + typedef void (Weiche::*WeicheSchalten)(void); + Weiche(IMotor& motor); + void Geradeaus(); + void Abzweigen(); + + private: + IMotor& _motor; + const int _speed=250; + const int _delay=50; + +}; + +#endif diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..7cde60c --- /dev/null +++ b/platformio.ini @@ -0,0 +1,18 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:uno] +platform = atmelavr +lib_deps = https://github.com/johnrickman/LiquidCrystal_I2C +board = uno +framework = arduino +monitor_speed = 115200 +upload_speed = 115200 + diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..4c32f62 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,139 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // Wire Bibliothek einbinden +#include // Vorher hinzugefügte LiquidCrystal_I2C Bibliothek einbinden + +L298n regler1(6,8,7); +L298n regler2(5,3,4); + + +Weiche weicheBahnhof1(regler2); +Gleis gleis1(weicheBahnhof1, &Weiche::Geradeaus); +Gleis gleis2(weicheBahnhof1, &Weiche::Abzweigen); + +Gleisabschnitt bahnhof1(9); +Gleisabschnitt bahnhof2(10); + +/* +Locomotive locomotiveTaurus(5, 22, 116, 180, regler1); +Locomotive locomotive2043(6, 25, 129, 160, regler1); +*/ +Locomotive locomotiveTaurus(5, 22, 58, 120, regler1); +Locomotive locomotive2043(6, 25, 70, 160, regler1); + +Fahrt fahrt[] = { + Fahrt(locomotiveTaurus, 135, motorForward, gleis1, bahnhof2, 6.7), + Fahrt(locomotiveTaurus, 125, motorBackward, gleis1, bahnhof1, 5.6) , + Fahrt(locomotive2043, 145, motorForward, gleis2, bahnhof2, 5.7), + Fahrt(locomotive2043, 148, motorBackward, gleis2, bahnhof1, 5.3) +}; + +int _currentFahrt; + +LiquidCrystal_I2C lcd(0x27, 16, 2); //Hier wird festgelegt um was für einen Display es sich handelt. In diesem Fall eines mit 16 Zeichen in 2 Zeilen und der HEX-Adresse 0x27. Für ein vierzeiliges I2C-LCD verwendet man den Code "LiquidCrystal_I2C lcd(0x27, 20, 4)" + +void initDisplay() +{ + lcd.setCursor(0, 0);//Hier wird die Position des ersten Zeichens festgelegt. In diesem Fall bedeutet (0,0) das erste Zeichen in der ersten Zeile. + lcd.print("Pendelzug n"); + lcd.setCursor(0, 1);// In diesem Fall bedeutet (0,1) das erste Zeichen in der zweiten Zeile. + lcd.print("v=000 s.br=00.00"); +} + +void dispFahrt(byte iFahrt) +{ + lcd.setCursor(10, 0);// In diesem Fall bedeutet (0,1) das erste Zeichen in der zweiten Zeile. + lcd.print(iFahrt); +} + +void dispSpeed(byte speed) +{ + lcd.setCursor(2, 1);// In diesem Fall bedeutet (0,1) das erste Zeichen in der zweiten Zeile. + lcd.print(" "); + lcd.setCursor(2, 1);// In diesem Fall bedeutet (0,1) das erste Zeichen in der zweiten Zeile. + lcd.print(speed); +} + +void dispBremsweg(float bremsweg) +{ + lcd.setCursor(11, 1);// In diesem Fall bedeutet (0,1) das erste Zeichen in der zweiten Zeile. + lcd.print(" "); + lcd.setCursor(11, 1);// In diesem Fall bedeutet (0,1) das erste Zeichen in der zweiten Zeile. + lcd.print(bremsweg); +} + +AnalogFiveButtonsDebounce a0button(A0, 15, 0, 31, 87, 165, 351); + +void CheckDeltaKeys(Fahrt& fahrt) +{ + byte key = a0button.changedButton(); + /* Serial.print("Sensor: "); + Serial.println(sensorValue); */ + + switch(key) { + case BTN_SELECT: { + + break; + } + case BTN_LEFT: { + Serial.println("ChangeBremsweg DOWN"); + dispBremsweg( fahrt.ChangeBremsweg(-0.3) ); + break; + } + case BTN_RIGHT: { + Serial.println("ChangeBremsweg UP"); + dispBremsweg( fahrt.ChangeBremsweg( 0.3) ); + break; + } + case BTN_UP: { + Serial.println("ChangeSpeed UP"); + dispSpeed( fahrt.ChangeSpeed( 5) ); + break; + } + case BTN_DOWN: { + Serial.println("ChangeSpeed DOWN"); + dispSpeed( fahrt.ChangeSpeed(-5) ); + break; + } + } +} + +void setup() { + // put your setup code here, to run once: + _currentFahrt=3; + Serial.begin(115200); + lcd.init(); //Im Setup wird der LCD gestartet + lcd.backlight(); //Hintergrundbeleuchtung einschalten (lcd.noBacklight(); schaltet die Beleuchtung aus). + initDisplay(); +}; + +void loop() { + + // put your main code here, to run repeatedly: + if (fahrt[_currentFahrt].IstAngekommen()) + { + delay(2000); + + Serial.println("Andere Fahrt"); + _currentFahrt = (_currentFahrt + 1) % 4; + fahrt[_currentFahrt].Vorbereiten(); + + dispFahrt(_currentFahrt+1); + dispSpeed( fahrt[_currentFahrt].ChangeSpeed(0) ); + dispBremsweg( fahrt[_currentFahrt].ChangeBremsweg( 0.0) ); + + delay(1000); + + fahrt[_currentFahrt].Start(); + } + CheckDeltaKeys(fahrt[_currentFahrt]); + fahrt[_currentFahrt].Loop(); +}; + diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html