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

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