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
This commit is contained in:
2023-05-14 21:22:04 +02:00
commit 349d1d644e
27 changed files with 1051 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

10
.vscode/extensions.json vendored Normal file
View File

@@ -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"
]
}

12
ErsterTest.code-workspace Normal file
View File

@@ -0,0 +1,12 @@
{
"folders": [
{
"path": "."
},
{
"name": "IR Remote",
"path": "../IR Remote"
}
],
"settings": {}
}

39
include/README Normal file
View File

@@ -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

View File

@@ -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 <inttypes.h>
#include <Arduino.h>
#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;
}

View File

@@ -0,0 +1,64 @@
// ensure this library description is only included once
#ifndef A5Bdb_h
#define A5Bdb_h
#include <inttypes.h>
#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

25
lib/Imotor/Imotor.cpp Normal file
View File

@@ -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);
}
*/

21
lib/Imotor/Imotor.h Normal file
View File

@@ -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

61
lib/L298n/L298n.cpp Normal file
View File

@@ -0,0 +1,61 @@
#include "IMotor.h"
#include <L298n.h>
#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);
}

22
lib/L298n/L298n.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef L298_h
#define L298_h
#include "Arduino.h"
#include <Imotor.h>
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

46
lib/README Normal file
View File

@@ -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 <Foo.h>
#include <Bar.h>
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

77
lib/fahrt/fahrt.cpp Normal file
View File

@@ -0,0 +1,77 @@
# include<Arduino.h>
#include<fahrt.h>
#include<locomotive.h>
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);
}

33
lib/fahrt/fahrt.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef Fahrt_h
#define Fahrt_h
#include<locomotive.h>
#include<gleis.h>
#include <Imotor.h>
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

14
lib/gleis/gleis.cpp Normal file
View File

@@ -0,0 +1,14 @@
#include <gleis.h>
#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)();
}

22
lib/gleis/gleis.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef Gleis_h
#define Gleis_h
#include "Arduino.h"
#include <locomotive.h>
#include <weiche.h>
#include <gleisabschnitt.h>
class Gleis
{
public:
Gleis();
Gleis(Weiche weiche, Weiche::WeicheSchalten weicheSchalten);
void Waehlen();
private:
Weiche _weiche;
Weiche::WeicheSchalten _weicheSchalten;
bool _keineWeiche;
};
#endif

View File

@@ -0,0 +1,14 @@
#include <Arduino.h>
#include <gleisabschnitt.h>
Gleisabschnitt::Gleisabschnitt(int pin) : _pin(pin)
{
pinMode(pin, INPUT_PULLUP);
};
bool Gleisabschnitt::IstBesetzt() {
if (digitalRead(_pin)==HIGH)
return false;
else
return true;
};

View File

@@ -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

View File

@@ -0,0 +1,119 @@
#include<locomotive.h>
#include<motor.h>
#include<math.h>
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<breakspeed) && (_currentAcc<0))
{
newspeed = 0;
_currentAcc = 0;
};
setSpeed(newspeed);
_millisStart = currentMillis; //IMPORTANT to save the start time of the current LED state.
}
};
byte Locomotive::currentSpeed()
{
return _currentSpeed;
};
byte Locomotive::getDefaultSpeed()
{
return _maxSpeed;
};

View File

@@ -0,0 +1,36 @@
#ifndef Locomotive_h
#define Locomotive_h
#include "Arduino.h"
#include "Imotor.h"
class Locomotive
{
public:
Locomotive(int accelerate, int decelerate, byte minSpeed, byte maxSpeed, IMotor& motor);
Locomotive(int accelerate, byte speed, int decelerate, byte minSpeed, byte maxSpeed, IMotor& motor);
void Accelerate();
void Accelerate(byte Speed);
void Accelerate(byte Speed, float bremsweg);
void Break();
void setSpeed(byte Speed);
void loop();
byte currentSpeed();
void setDirection(MotorDirection dir);
byte getDefaultSpeed();
private:
int _accelerate;
int _decelerate;
int _currentAcc;
byte _minSpeed;
byte _maxSpeed;
byte _targetSpeed;
const unsigned int _delay=300;
unsigned long _millisStart;
byte _currentSpeed;
IMotor& _motor;
};
#endif

7
lib/motor/dfquad.h Normal file
View File

@@ -0,0 +1,7 @@
#include "motor.h"
/* Motor mot1(3, 4, LOW);
Motor mot2(11, 12, HIGH);
Motor mot3(5, 8, LOW);
Motor mot4(6, 7, HIGH);
*/

47
lib/motor/motor.cpp Normal file
View File

@@ -0,0 +1,47 @@
#include "Motor.h"
#include "Arduino.h"
Motor::Motor(int pinPwm, int pinDir, int dirForward)
{
_pinPwm = pinPwm;
_pinDir = pinDir;
_dirForward = dirForward;
if (dirForward==LOW)
{
_dirForward=LOW;
_dirBackward=HIGH;
}
else
{
_dirForward=HIGH;
_dirBackward=LOW;
}
_currentDir = motorForward;
pinMode(_pinPwm,OUTPUT);
pinMode(_pinDir,OUTPUT);
}
void Motor::setSpeed(int speed)
{
setDirection (_currentDir);
analogWrite(_pinPwm, speed);
}
void Motor::setDirection(MotorDirection dir)
{
_currentDir=dir;
if (_currentDir == motorForward)
{
digitalWrite(_pinDir, _dirForward);
}
else
{
digitalWrite(_pinDir, _dirBackward);
}
}
void Motor::Stop()
{
setSpeed (0);
}

22
lib/motor/motor.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef Motor_h
#define Motor_h
#include "Arduino.h"
#include "Imotor.h"
class Motor: public IMotor
{
public:
Motor(int pinPwm, int pinDir, int dirForward);
virtual void setSpeed(int speed) override;
virtual void setDirection(MotorDirection dir) override;
virtual void Stop() override;
private:
int _pinDir;
int _dirForward;
int _dirBackward;
};
#endif

26
lib/weiche/weiche.cpp Normal file
View File

@@ -0,0 +1,26 @@
#include <weiche.h>
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("--");
}

21
lib/weiche/weiche.h Normal file
View File

@@ -0,0 +1,21 @@
#ifndef Weiche_h
#define Weiche_h
# include <motor.h>
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

18
platformio.ini Normal file
View File

@@ -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

139
src/main.cpp Normal file
View File

@@ -0,0 +1,139 @@
#include <Arduino.h>
#include <dfquad.h>
#include <motor.h>
#include <locomotive.h>
#include <gleis.h>
#include <fahrt.h>
#include <weiche.h>
#include <L298n.h>
#include <AnalogFiveButtons.h>
#include <Wire.h> // Wire Bibliothek einbinden
#include <LiquidCrystal_I2C.h> // 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();
};

11
test/README Normal file
View File

@@ -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