Init: Rattenfalle
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "core"]
|
||||
path = core
|
||||
url = git@github.com:Gustice/ArduinoDevicePlatform.git
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
// 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",
|
||||
"pioarduino.pioarduino-ide"
|
||||
]
|
||||
}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"C_Cpp.autoAddFileAssociations": false,
|
||||
|
||||
"C_Cpp.clang_format_style": "{BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 0}",
|
||||
"C_Cpp.clang_format_fallbackStyle": "{ BasedOnStyle: LLVM, UseTab: Never, IndentWidth: 4, TabWidth: 4, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: false, ColumnLimit: 0, AccessModifierOffset: -4, NamespaceIndentation: All, FixNamespaceComments: false }",
|
||||
}
|
||||
Submodule
+1
Submodule core added at 4a1e39b6aa
@@ -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
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Servo.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "AbHal.hpp"
|
||||
#include "DcMotor.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
|
||||
using TimeStamp = decltype(millis());
|
||||
|
||||
class ServoGrp {
|
||||
public:
|
||||
ServoGrp(int pin) : _pin(pin) {}
|
||||
|
||||
void attach() {
|
||||
_srv.attach(_pin);
|
||||
}
|
||||
|
||||
void detach() {
|
||||
_srv.detach();
|
||||
}
|
||||
|
||||
void write(int pos) {
|
||||
_pos = pos;
|
||||
_srv.write(_pos);
|
||||
}
|
||||
|
||||
private:
|
||||
Servo _srv;
|
||||
int _pin;
|
||||
int _pos{};
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* @file DcMotor.hpp
|
||||
* @author Gustice
|
||||
* @brief Simple Driver implementation for DRVxxxx Derivatives from Texas instruments
|
||||
* DRV8848
|
||||
*
|
||||
* @copyright Copyright (c) 2024
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
class DcMotor {
|
||||
static constexpr int FullScale = 256;
|
||||
|
||||
public:
|
||||
struct Pins {
|
||||
std::array<int, 2> PwmA; // PWM control
|
||||
int ErrorIn; // Error Feedback from driver
|
||||
int Sleep; // Sleep control (to enter double mode)
|
||||
int Ceil; // Maximum speed control
|
||||
int ErrOut; // Maximum speed control
|
||||
};
|
||||
|
||||
enum State {
|
||||
Startup = 0,
|
||||
Idle,
|
||||
Right,
|
||||
Left,
|
||||
};
|
||||
|
||||
DcMotor(Pins pins) : _pins(pins) {
|
||||
pinMode(_pins.PwmA[0], OUTPUT);
|
||||
pinMode(_pins.PwmA[1], OUTPUT);
|
||||
pinMode(_pins.ErrorIn, INPUT);
|
||||
pinMode(_pins.Sleep, OUTPUT);
|
||||
pinMode(_pins.Ceil, INPUT);
|
||||
pinMode(_pins.ErrOut, OUTPUT);
|
||||
|
||||
// sleep to enter double current mode
|
||||
delay(5);
|
||||
digitalWrite(_pins.Sleep, LOW);
|
||||
delay(5); // @todo double after successful operation
|
||||
digitalWrite(_pins.Sleep, HIGH);
|
||||
|
||||
// set to break
|
||||
analogWrite(_pins.PwmA[0], FullScale);
|
||||
analogWrite(_pins.PwmA[1], FullScale);
|
||||
}
|
||||
|
||||
void stop() {
|
||||
analogWrite(_pins.PwmA[0], FullScale);
|
||||
analogWrite(_pins.PwmA[1], FullScale);
|
||||
|
||||
_state = Idle;
|
||||
}
|
||||
|
||||
void startRight() {
|
||||
int ceil = analogRead(_pins.Ceil) / 4;
|
||||
_state = Right;
|
||||
|
||||
analogWrite(_pins.PwmA[0], FullScale);
|
||||
analogWrite(_pins.PwmA[1], FullScale - ceil);
|
||||
}
|
||||
|
||||
void startLeft() {
|
||||
int ceil = analogRead(_pins.Ceil) / 4;
|
||||
_state = Left;
|
||||
|
||||
analogWrite(_pins.PwmA[0], FullScale - ceil);
|
||||
analogWrite(_pins.PwmA[1], FullScale);
|
||||
}
|
||||
|
||||
void tick() {
|
||||
int ceil = analogRead(_pins.Ceil) / 4;
|
||||
|
||||
switch (_state) {
|
||||
case Right:
|
||||
analogWrite(_pins.PwmA[1], FullScale - ceil);
|
||||
break;
|
||||
|
||||
case Left:
|
||||
analogWrite(_pins.PwmA[0], FullScale - ceil);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
int nErr = digitalRead(_pins.ErrorIn);
|
||||
digitalWrite(_pins.ErrOut, nErr == 0);
|
||||
}
|
||||
|
||||
private:
|
||||
Pins _pins;
|
||||
State _state = Startup;
|
||||
};
|
||||
+46
@@ -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
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @file RotatingIndex.hpp
|
||||
* @author Gustice
|
||||
* @brief Classes for typical index manipulation
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief Index with automatic revolution back to start position
|
||||
* @details Useful for Buffer-Pointer, or similar tasks
|
||||
*
|
||||
* @tparam T Numeric type
|
||||
*/
|
||||
template <typename T = int>
|
||||
class RotatingIndex {
|
||||
public:
|
||||
/// @brief Value at witch the index rotates back to beginning
|
||||
const T MaxIndex;
|
||||
|
||||
/**
|
||||
* @brief Constructor for rotating index
|
||||
* @brief output index will be set to 0 if incremented value reaches Maximum
|
||||
* @param max Maximum index for overflow-condition
|
||||
*/
|
||||
RotatingIndex(T max) : MaxIndex(max) {
|
||||
_index = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current index and increment index afterwards
|
||||
* @return T current index
|
||||
*/
|
||||
T GetIndexAndIncrement() {
|
||||
auto retVal = _index;
|
||||
_index++;
|
||||
if (_index >= MaxIndex) {
|
||||
_index = 0;
|
||||
}
|
||||
return retVal;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get the current index without incrementing the index
|
||||
* @return T current index
|
||||
*/
|
||||
T GetIndex() const {
|
||||
return _index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increments index and retuns if index has been reset
|
||||
*/
|
||||
bool IncrementAndCheckIfRevolves() {
|
||||
_index++;
|
||||
if (_index >= MaxIndex) {
|
||||
_index = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset Index to 0
|
||||
*/
|
||||
void ResetIndex() {
|
||||
_index = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Current Index
|
||||
T _index;
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
; 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
|
||||
|
||||
# Base for embedded environments
|
||||
[env]
|
||||
test_framework = unity
|
||||
test_filter = embedded/test_*
|
||||
; debug_test = embedded/test_...
|
||||
lib_extra_dirs = core/lib
|
||||
; build_unflags = -std=gnu++11
|
||||
; build_flags = -std=c++20
|
||||
|
||||
[env:Lair]
|
||||
# Board: https://docs.platformio.org/en/latest/boards/atmelsam/seeed_xiao.html
|
||||
platform = renesas-ra
|
||||
board = nano_r4
|
||||
framework = arduino
|
||||
build_unflags = -std=gnu++11
|
||||
build_flags = -std=c++20
|
||||
build_src_filter =
|
||||
-<*>
|
||||
+<mainLair.cpp>
|
||||
platform_packages =
|
||||
toolchain-gccarmnoneeabi@~1.120301.0
|
||||
lib_deps =
|
||||
arduino-libraries/Servo @ ^1.3.0
|
||||
|
||||
; mainControl.cpp
|
||||
|
||||
# Native environment (Host PC)
|
||||
[env:native]
|
||||
# overwrite embedded related setup
|
||||
test_framework = googletest
|
||||
platform=native
|
||||
test_filter = native/test_*
|
||||
; debug_test = native/test_...
|
||||
@@ -0,0 +1,472 @@
|
||||
#include "main.hpp"
|
||||
|
||||
using namespace abh;
|
||||
|
||||
Input extResetGame(0);
|
||||
|
||||
Output Magnet1(1);
|
||||
Output Magnet2(3);
|
||||
Servo Servo1;
|
||||
Servo Servo2;
|
||||
|
||||
Input endSwitch1(2);
|
||||
Input endSwitch2(3);
|
||||
|
||||
#define Rfid1
|
||||
|
||||
Output SLedPin(LED_BUILTIN, abh::Port::LogicType::Inverted);
|
||||
static StatusLed _statusLed(SLedPin);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
_statusLed.set(StatusLed::Mode::DoubleFlash);
|
||||
|
||||
Servo1.attach(2);
|
||||
Servo2.attach(3);
|
||||
|
||||
Servo1.write(45);
|
||||
Servo2.write(90);
|
||||
}
|
||||
|
||||
State state{};
|
||||
|
||||
void loop() {
|
||||
static Tick tick(5);
|
||||
static Tick diagTick(250);
|
||||
static Tick servoTick(2000);
|
||||
|
||||
if (!tick) {
|
||||
return;
|
||||
}
|
||||
static int servo{};
|
||||
|
||||
if (servoTick) {
|
||||
servo++;
|
||||
if (servo % 2) {
|
||||
Servo1.write(45);
|
||||
Servo2.write(0);
|
||||
} else {
|
||||
Servo1.write(90);
|
||||
Servo2.write(180);
|
||||
}
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
default:
|
||||
case Idle: {
|
||||
state = Start;
|
||||
} break;
|
||||
|
||||
case Start: {
|
||||
state = Running;
|
||||
} break;
|
||||
|
||||
case Running: {
|
||||
state = Idle;
|
||||
} break;
|
||||
}
|
||||
|
||||
if (diagTick) {
|
||||
_statusLed.tick();
|
||||
Serial.printf("S=%d 0=%d | s=%d \r\n", (bool)true, (bool)false, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <Servo.h>
|
||||
|
||||
const int BUFFER_SIZE = 14; // RFID DATA FRAME FORMAT: 1byte head (value: 2), 10byte data (2byte version + 8byte tag), 2byte checksum, 1byte tail (value: 3)
|
||||
const int DATA_SIZE = 10; // 10byte data (2byte version + 8byte tag)
|
||||
const int DATA_VERSION_SIZE = 2; // 2byte version (actual meaning of these two bytes may vary)
|
||||
const int DATA_TAG_SIZE = 8; // 8byte tag
|
||||
const int CHECKSUM_SIZE = 2; // 2byte checksum
|
||||
uint8_t buffer[BUFFER_SIZE]; // used to store an incoming data frame
|
||||
int buffer_index = 0;
|
||||
String data;
|
||||
int datainteger;
|
||||
|
||||
Servo tor_servo; // Tor mit Ratte
|
||||
Servo tor2_servo; // Großes Tor in der Ecke
|
||||
|
||||
#define Reset 52
|
||||
#define LED 7
|
||||
#define Schloss1 46
|
||||
#define Schloss2 47
|
||||
#define Tortasteroffen 32
|
||||
#define Tortastergeschlossen 28
|
||||
|
||||
int servo_position, success, tortasterzustand, tortasterzaehler = 0;
|
||||
int sollID = 9715;
|
||||
int sollID2 = 22907;
|
||||
int torzustand = 0; //0=zu | 1=offen
|
||||
int torFalleTasterOffenZustand, torFalleTasterZuZustand = 0;
|
||||
int buttonState; // the current reading from the input pin
|
||||
int lastButtonState = LOW; // the previous reading from the input pin
|
||||
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
|
||||
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
|
||||
unsigned long motorsafetyTime = 0;
|
||||
unsigned long motorsafetyTimeDelay = 5000;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial1.begin(115200);
|
||||
Serial3.begin(9600);
|
||||
pinMode(Reset, INPUT);
|
||||
pinMode(Tortasteroffen, INPUT);
|
||||
pinMode(Tortastergeschlossen, INPUT);
|
||||
pinMode(LED, OUTPUT);
|
||||
pinMode(Schloss1, OUTPUT);
|
||||
digitalWrite(Schloss1, HIGH);
|
||||
pinMode(Schloss2, OUTPUT);
|
||||
digitalWrite(Schloss2, HIGH);
|
||||
digitalWrite(LED, HIGH);
|
||||
|
||||
//Torzustand erfragen
|
||||
torFalleTasterOffenZustand = digitalRead(Tortasteroffen);
|
||||
torFalleTasterZuZustand = digitalRead(Tortastergeschlossen);
|
||||
Serial.print("Fallentortasteroffen: ");
|
||||
Serial.println(torFalleTasterOffenZustand);
|
||||
Serial.print("Fallentortastergeschlossen: ");
|
||||
Serial.println(torFalleTasterZuZustand);
|
||||
Serial.println("-------------------------------");
|
||||
|
||||
if(torFalleTasterOffenZustand == 0) {
|
||||
Serial.println("FallenTor ist offen");
|
||||
torzustand=1;
|
||||
} else {
|
||||
Serial.println("FallenTor ist zu");
|
||||
digitalWrite(LED, LOW);
|
||||
tor_offnen();
|
||||
}
|
||||
|
||||
Serial.println("INIT DONE");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int reading = digitalRead(Reset);
|
||||
if (reading != lastButtonState) {
|
||||
lastDebounceTime = millis();
|
||||
}
|
||||
|
||||
if ((millis() - lastDebounceTime) > debounceDelay) {
|
||||
if (reading != buttonState) {
|
||||
buttonState = reading;
|
||||
if (buttonState == HIGH && torzustand==1) {
|
||||
Serial.println("Resettaster wurde gedrückt");
|
||||
tor_schliessen();
|
||||
}
|
||||
}
|
||||
}
|
||||
lastButtonState = reading;
|
||||
|
||||
if (Serial3.available() > 0 && torzustand==0) {
|
||||
bool call_extract_tag = false;
|
||||
int ssvalue = Serial3.read(); // read
|
||||
Serial.println(ssvalue);
|
||||
if (ssvalue == -1) { // no data was read
|
||||
return;
|
||||
}
|
||||
if (ssvalue == 2) { // RDM630/RDM6300 found a tag => tag incoming
|
||||
buffer_index = 0;
|
||||
} else if (ssvalue == 3) { // tag has been fully transmitted
|
||||
call_extract_tag = true; // extract tag at the end of the function call
|
||||
}
|
||||
if (buffer_index >= BUFFER_SIZE) { // checking for a buffer overflow (It's very unlikely that an buffer overflow comes up!)
|
||||
Serial.println("Error: Buffer overflow detected!");
|
||||
return;
|
||||
}
|
||||
|
||||
buffer[buffer_index++] = ssvalue; // everything is alright => copy current value to buffer
|
||||
if (call_extract_tag == true && success == 0) {
|
||||
if (buffer_index == BUFFER_SIZE) {
|
||||
unsigned tag = extract_tag();
|
||||
Serial.println(tag);
|
||||
if (tag == sollID || tag == sollID2) {
|
||||
Serial.println("Herzlichen Glückwunsch Sie haben erfolgreich eine Ratte gefangen!");
|
||||
tor_offnen();
|
||||
}
|
||||
} else { // something is wrong... start again looking for preamble (value: 2)
|
||||
buffer_index = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (Serial3.available() > 0 && torzustand==1) {
|
||||
while (Serial3.available() > 0) {
|
||||
Serial3.read();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned extract_tag() {
|
||||
uint8_t msg_head = buffer[0];
|
||||
uint8_t *msg_data = buffer + 1; // 10 byte => data contains 2byte version + 8byte tag
|
||||
uint8_t *msg_data_version = msg_data;
|
||||
uint8_t *msg_data_tag = msg_data + 2;
|
||||
uint8_t *msg_checksum = buffer + 11; // 2 byte
|
||||
uint8_t msg_tail = buffer[13];
|
||||
// print message that was sent from RDM630/RDM6300
|
||||
Serial.println("--------");
|
||||
Serial.print("Message-Head: ");
|
||||
Serial.println(msg_head);
|
||||
Serial.println("Message-Data (HEX): ");
|
||||
for (int i = 0; i < DATA_VERSION_SIZE; ++i) {
|
||||
Serial.print(char(msg_data_version[i]));
|
||||
}
|
||||
Serial.println(" (version)");
|
||||
for (int i = 0; i < DATA_TAG_SIZE; ++i) {
|
||||
Serial.print(char(msg_data_tag[i]));
|
||||
}
|
||||
Serial.println(" (tag)");
|
||||
Serial.print("Message-Checksum (HEX): ");
|
||||
for (int i = 0; i < CHECKSUM_SIZE; ++i) {
|
||||
Serial.print(char(msg_checksum[i]));
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.print("Message-Tail: ");
|
||||
Serial.println(msg_tail);
|
||||
Serial.println("--");
|
||||
long tag = hexstr_to_value(msg_data_tag, DATA_TAG_SIZE);
|
||||
Serial.print("Extracted Tag: ");
|
||||
Serial.println(tag);
|
||||
long checksum = 0;
|
||||
for (int i = 0; i < DATA_SIZE; i += CHECKSUM_SIZE) {
|
||||
long val = hexstr_to_value(msg_data + i, CHECKSUM_SIZE);
|
||||
checksum ^= val;
|
||||
}
|
||||
Serial.print("Extracted Checksum (HEX): ");
|
||||
Serial.print(checksum, HEX);
|
||||
if (checksum == hexstr_to_value(msg_checksum, CHECKSUM_SIZE)) { // compare calculated checksum to retrieved checksum
|
||||
Serial.print(" (OK)"); // calculated checksum corresponds to transmitted checksum!
|
||||
} else {
|
||||
Serial.print(" (NOT OK)"); // checksums do not match
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("--------");
|
||||
return tag;
|
||||
}
|
||||
long hexstr_to_value(char *str, unsigned int length) { // converts a hexadecimal value (encoded as ASCII string) to a numeric value
|
||||
char* copy = malloc((sizeof(char) * length) + 1);
|
||||
memcpy(copy, str, sizeof(char) * length);
|
||||
copy[length] = '\0';
|
||||
// the variable "copy" is a copy of the parameter "str". "copy" has an additional '\0' element to make sure that "str" is null-terminated.
|
||||
long value = strtol(copy, NULL, 16); // strtol converts a null-terminated string to a long value
|
||||
free(copy); // clean up
|
||||
return value;
|
||||
}
|
||||
//Hakentor ist bei 76 Grad zu | Rattentor bei 85 Grad
|
||||
void tor_offnen() {
|
||||
if(torzustand==0) {
|
||||
Serial.println("öffnen");
|
||||
digitalWrite(LED, HIGH);
|
||||
//tor_servo.write(0);
|
||||
|
||||
motorsafetyTime = millis();
|
||||
digitalWrite(Schloss1, LOW);
|
||||
|
||||
|
||||
int servo_position = 200;
|
||||
//FallenTor
|
||||
tor2_servo.attach (9);
|
||||
while (digitalRead(Tortasteroffen) == 1){
|
||||
if ((millis() - motorsafetyTime) > motorsafetyTimeDelay) {
|
||||
//kill Tor öffnen es dauert zu lang
|
||||
digitalWrite(Schloss1, HIGH);
|
||||
Serial.println("Es hat zu lange gedauert. Etwas stimmt nicht. Das Tor öffnen wurde beendet #1");
|
||||
break;
|
||||
}
|
||||
servo_position--;
|
||||
tor2_servo.write(servo_position);
|
||||
delay(10);
|
||||
}
|
||||
int test = servo_position+10;
|
||||
tor2_servo.write(test);
|
||||
delay(20);
|
||||
tor2_servo.detach();
|
||||
Serial.println("FallenTor offen");
|
||||
|
||||
digitalWrite(Schloss1, HIGH);
|
||||
digitalWrite(Schloss2, LOW);
|
||||
|
||||
//RattenTor
|
||||
tor_servo.attach (4);
|
||||
for(servo_position = 83; servo_position >=0; servo_position -=1){
|
||||
if ((millis() - motorsafetyTime) > motorsafetyTimeDelay) {
|
||||
//kill Tor öffnen es dauert zu lang
|
||||
digitalWrite(Schloss2, HIGH);
|
||||
Serial.println("Es hat zu lange gedauert. Etwas stimmt nicht. Das Tor öffnen wurde beendet #2");
|
||||
break;
|
||||
}
|
||||
tor_servo.write(servo_position);
|
||||
delay(10);
|
||||
}
|
||||
tor_servo.detach();
|
||||
Serial.println("RattennTor offen");
|
||||
|
||||
|
||||
digitalWrite(Schloss2, HIGH);
|
||||
Serial.println("Alle Elektroschlösser entspannt");
|
||||
|
||||
//tor2_servo.write(0);
|
||||
if ((millis() - motorsafetyTime) > motorsafetyTimeDelay) {
|
||||
//kill Tor öffnen es dauert zu lang
|
||||
Serial.println("Es hat zu lange gedauert. Etwas stimmt nicht. Das Tor öffnen wurde beendet #3");
|
||||
} else {
|
||||
torzustand = 1;
|
||||
Serial.println("1Torzustand = 1 - Tore wurden geöffnet");
|
||||
}
|
||||
}
|
||||
while (Serial3.available() > 0) {
|
||||
Serial3.read();
|
||||
}
|
||||
}
|
||||
void tor_schliessen() {
|
||||
if(torzustand==1) {
|
||||
Serial.println("schliessen");
|
||||
digitalWrite(LED, LOW);
|
||||
//RattenTor
|
||||
tor_servo.attach (4);
|
||||
for(servo_position = 0; servo_position <=83; servo_position +=1){
|
||||
tor_servo.write(servo_position);
|
||||
delay(10);
|
||||
}
|
||||
tor_servo.detach();
|
||||
int servo_position = 0;
|
||||
//FallenTor
|
||||
tor2_servo.attach (9);
|
||||
while (digitalRead(Tortastergeschlossen) == 1){
|
||||
servo_position++;
|
||||
tor2_servo.write(servo_position);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
int test = servo_position-3;
|
||||
tor2_servo.write(test);
|
||||
delay(20);
|
||||
tor2_servo.detach();
|
||||
|
||||
torzustand = 0;
|
||||
Serial.println("2Torzustand = 0 - Tore wurden geschlossen");
|
||||
}
|
||||
while (Serial3.available() > 0) {
|
||||
Serial3.read();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Hakentor ist bei 76 Grad zu | Rattentor bei 85 Grad
|
||||
void openDor() {
|
||||
if (!DoorIsOpen) {
|
||||
Serial.println("--open");
|
||||
|
||||
auto motorsafetyTime = millis();
|
||||
DoorLock.write(false); // digitalWrite(Schloss1, LOW);
|
||||
|
||||
int servo_position = 200;
|
||||
// FallenTor
|
||||
while (digitalRead(Tortasteroffen) == 1) {
|
||||
if ((millis() - motorsafetyTime) > motorsafetyTimeDelay) {
|
||||
// kill Tor öffnen es dauert zu lang
|
||||
digitalWrite(Schloss1, HIGH);
|
||||
Serial.println("Es hat zu lange gedauert. Etwas stimmt nicht. Das Tor öffnen wurde beendet #1");
|
||||
break;
|
||||
}
|
||||
servo_position--;
|
||||
tor2_servo.write(servo_position);
|
||||
delay(10);
|
||||
}
|
||||
int test = servo_position + 10;
|
||||
tor2_servo.write(test);
|
||||
delay(20);
|
||||
tor2_servo.detach();
|
||||
Serial.println("FallenTor offen");
|
||||
|
||||
digitalWrite(Schloss1, HIGH);
|
||||
digitalWrite(Schloss2, LOW);
|
||||
|
||||
// RattenTor
|
||||
for (servo_position = 83; servo_position >= 0; servo_position -= 1) {
|
||||
if ((millis() - motorsafetyTime) > motorsafetyTimeDelay) {
|
||||
// kill Tor öffnen es dauert zu lang
|
||||
digitalWrite(Schloss2, HIGH);
|
||||
Serial.println("Es hat zu lange gedauert. Etwas stimmt nicht. Das Tor öffnen wurde beendet #2");
|
||||
break;
|
||||
}
|
||||
ratDoor.write(servo_position);
|
||||
delay(10);
|
||||
}
|
||||
ratDoor.detach();
|
||||
Serial.println("RattennTor offen");
|
||||
|
||||
digitalWrite(Schloss2, HIGH);
|
||||
Serial.println("Alle Elektroschlösser entspannt");
|
||||
|
||||
// tor2_servo.write(0);
|
||||
if ((millis() - motorsafetyTime) > motorsafetyTimeDelay) {
|
||||
// kill Tor öffnen es dauert zu lang
|
||||
Serial.println("Es hat zu lange gedauert. Etwas stimmt nicht. Das Tor öffnen wurde beendet #3");
|
||||
} else {
|
||||
DoorIsOpen = true;
|
||||
Serial.println("1DoorIsOpen = 1 - Tore wurden geöffnet");
|
||||
}
|
||||
}
|
||||
}
|
||||
void closeDoor() {
|
||||
if (DoorIsOpen) {
|
||||
Serial.println("--close");
|
||||
// RattenTor
|
||||
ratDoor.attach(4);
|
||||
for (servo_position = 0; servo_position <= 83; servo_position += 1) {
|
||||
ratDoor.write(servo_position);
|
||||
delay(10);
|
||||
}
|
||||
ratDoor.detach();
|
||||
int servo_position = 0;
|
||||
// FallenTor
|
||||
tor2_servo.attach(9);
|
||||
while (digitalRead(DoorClodedPin) == 1) {
|
||||
servo_position++;
|
||||
tor2_servo.write(servo_position);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
int test = servo_position - 3;
|
||||
tor2_servo.write(test);
|
||||
delay(20);
|
||||
tor2_servo.detach();
|
||||
|
||||
DoorIsOpen = false;
|
||||
Serial.println(" -- close door");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
#include "main.hpp"
|
||||
|
||||
using namespace abh;
|
||||
|
||||
constexpr TimeStamp motorsafetyTimeDelay = 5000;
|
||||
constexpr int ServoStartPos = 0;
|
||||
constexpr int ServoEndPos = 83;
|
||||
|
||||
Output SLedPin(LED_BUILTIN);
|
||||
|
||||
Output DoorLock(14);
|
||||
Input endSwitchOpen(19);
|
||||
Input endSwitchClose(21);
|
||||
|
||||
Input openDoorCmd(9);
|
||||
Output doorOpendRes(8);
|
||||
ServoGrp DoorServo(3);
|
||||
|
||||
static StatusLed _statusLed(SLedPin);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
_statusLed.set(StatusLed::Mode::DoubleFlash);
|
||||
|
||||
doorOpendRes.write(false);
|
||||
}
|
||||
|
||||
enum State {
|
||||
WaitForOpenCmd,
|
||||
Open,
|
||||
WaitForCloseCmd,
|
||||
Close
|
||||
};
|
||||
|
||||
State state{};
|
||||
|
||||
void openDor();
|
||||
void closeDoor();
|
||||
|
||||
void loop() {
|
||||
static Tick tick(5);
|
||||
static Tick diagTick(250);
|
||||
if (!tick) {
|
||||
return;
|
||||
}
|
||||
|
||||
openDoorCmd.sample();
|
||||
endSwitchOpen.sample();
|
||||
endSwitchClose.sample();
|
||||
|
||||
switch (state) {
|
||||
default:
|
||||
case WaitForOpenCmd: {
|
||||
if (openDoorCmd.get() == Input::State::Active) {
|
||||
state = State::Open;
|
||||
}
|
||||
} break;
|
||||
|
||||
case Open: {
|
||||
DoorLock.write(true);
|
||||
openDor();
|
||||
DoorLock.write(false);
|
||||
doorOpendRes.write(true);
|
||||
|
||||
state = State::WaitForCloseCmd;
|
||||
} break;
|
||||
|
||||
case WaitForCloseCmd: {
|
||||
if (openDoorCmd.get() == Input::State::Passive) {
|
||||
state = State::Close;
|
||||
}
|
||||
} break;
|
||||
|
||||
case Close: {
|
||||
closeDoor();
|
||||
doorOpendRes.write(false);
|
||||
state = WaitForOpenCmd;
|
||||
} break;
|
||||
}
|
||||
|
||||
if (diagTick) {
|
||||
_statusLed.tick();
|
||||
char buff[256];
|
||||
sprintf(buff, "S=%d | cI=%d sO=%d sC%d \r\n",
|
||||
state, openDoorCmd.get(), endSwitchOpen.get(), endSwitchClose.get());
|
||||
Serial.print(buff);
|
||||
}
|
||||
}
|
||||
|
||||
void openDor() {
|
||||
Serial.println("--open");
|
||||
auto motorsafetyTime = millis();
|
||||
DoorServo.attach();
|
||||
for (int pos = ServoEndPos; pos >= ServoStartPos; pos -= 1) {
|
||||
if ((millis() - motorsafetyTime) > motorsafetyTimeDelay) { // prvent overheating
|
||||
Serial.println("Abort due to timeout");
|
||||
DoorServo.detach();
|
||||
return;
|
||||
}
|
||||
DoorServo.write(pos);
|
||||
delay(10);
|
||||
}
|
||||
DoorServo.detach();
|
||||
Serial.println("--isOpen");
|
||||
}
|
||||
|
||||
void closeDoor() {
|
||||
Serial.println("--close");
|
||||
DoorServo.attach();
|
||||
for (int pos = ServoStartPos; pos <= ServoEndPos; pos += 1) {
|
||||
DoorServo.write(pos);
|
||||
delay(10);
|
||||
}
|
||||
DoorServo.detach();
|
||||
Serial.println("--isClosed");
|
||||
}
|
||||
+11
@@ -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
|
||||
@@ -0,0 +1,83 @@
|
||||
#include "StatusLed.h"
|
||||
#include <Arduino.h>
|
||||
#include <unity.h>
|
||||
|
||||
void setUp(void) {}
|
||||
|
||||
void tearDown(void) {}
|
||||
|
||||
int LED_PIN = LED_BUILTIN;
|
||||
|
||||
void test_LedStaysDark(void) {
|
||||
StatusLed dut(LED_PIN);
|
||||
|
||||
for (size_t i = 0; i < 30; i++) {
|
||||
dut.Tick();
|
||||
TEST_ASSERT_EQUAL(LOW, digitalRead(LED_PIN));
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
void test_LedIsConstantOn(void) {
|
||||
StatusLed dut(LED_PIN);
|
||||
|
||||
dut.Set(StatusLed::Mode::SteadyOn);
|
||||
for (size_t i = 0; i < 30; i++) {
|
||||
dut.Tick();
|
||||
TEST_ASSERT_EQUAL(HIGH, digitalRead(LED_PIN));
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
void test_LedBlinks(void) {
|
||||
StatusLed dut(LED_PIN);
|
||||
|
||||
dut.Set(StatusLed::Mode::Blinking);
|
||||
for (size_t n = 0; n < 2; n++) {
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
dut.Tick();
|
||||
TEST_ASSERT_EQUAL(HIGH, digitalRead(LED_PIN));
|
||||
delay(20);
|
||||
}
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
dut.Tick();
|
||||
TEST_ASSERT_EQUAL(LOW, digitalRead(LED_PIN));
|
||||
delay(20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_LedBlinks_InverseLogic(void) {
|
||||
StatusLed dut(LED_PIN, StatusLed::LedLogic::Inverted);
|
||||
|
||||
dut.Set(StatusLed::Mode::Blinking);
|
||||
for (size_t n = 0; n < 2; n++) {
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
dut.Tick();
|
||||
TEST_ASSERT_EQUAL(LOW, digitalRead(LED_PIN));
|
||||
delay(20);
|
||||
}
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
dut.Tick();
|
||||
TEST_ASSERT_EQUAL(HIGH, digitalRead(LED_PIN));
|
||||
delay(20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// NOTE!!! Wait for >2 secs
|
||||
// if board doesn't support software reset via Serial.DTR/RTS
|
||||
delay(2000);
|
||||
|
||||
UNITY_BEGIN(); // IMPORTANT LINE!
|
||||
RUN_TEST(test_LedStaysDark);
|
||||
RUN_TEST(test_LedIsConstantOn);
|
||||
RUN_TEST(test_LedBlinks);
|
||||
RUN_TEST(test_LedBlinks_InverseLogic);
|
||||
UNITY_END(); // stop unit testing
|
||||
}
|
||||
|
||||
void loop() {
|
||||
delay(500);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
Import("env")
|
||||
|
||||
def after_upload(source, target, env):
|
||||
import time
|
||||
time.sleep(2)
|
||||
|
||||
env.AddPostAction("upload", after_upload)
|
||||
@@ -0,0 +1,71 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "RotatingIndex.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
if (RUN_ALL_TESTS())
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(RotatingIndex, Construction) {
|
||||
RotatingIndex<int> sut(4);
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
|
||||
TEST(RotatingIndex, InitialState) {
|
||||
RotatingIndex<int> sut(4);
|
||||
ASSERT_EQ(sut.GetIndex(), 0);
|
||||
}
|
||||
|
||||
TEST(RotatingIndex, TestOverflowWithGetIndexMethod) {
|
||||
RotatingIndex<int> sut(4);
|
||||
|
||||
ASSERT_EQ(sut.GetIndexAndIncrement(), 0);
|
||||
ASSERT_EQ(sut.GetIndexAndIncrement(), 1);
|
||||
ASSERT_EQ(sut.GetIndexAndIncrement(), 2);
|
||||
ASSERT_EQ(sut.GetIndexAndIncrement(), 3);
|
||||
ASSERT_EQ(sut.GetIndexAndIncrement(), 0);
|
||||
ASSERT_EQ(sut.GetIndexAndIncrement(), 1);
|
||||
}
|
||||
|
||||
TEST(RotatingIndex, TestOverflowWithCheckIfRevolvesMethod) {
|
||||
RotatingIndex<int> sut(4);
|
||||
|
||||
ASSERT_FALSE(sut.IncrementAndCheckIfRevolves());
|
||||
ASSERT_FALSE(sut.IncrementAndCheckIfRevolves());
|
||||
ASSERT_FALSE(sut.IncrementAndCheckIfRevolves());
|
||||
ASSERT_TRUE(sut.IncrementAndCheckIfRevolves());
|
||||
ASSERT_FALSE(sut.IncrementAndCheckIfRevolves());
|
||||
ASSERT_FALSE(sut.IncrementAndCheckIfRevolves());
|
||||
}
|
||||
|
||||
TEST(RotatingIndex, GetIndexReturnsCorrectValue) {
|
||||
RotatingIndex<int> sut(4);
|
||||
|
||||
ASSERT_EQ(sut.GetIndexAndIncrement(), 0);
|
||||
ASSERT_EQ(sut.GetIndex(), 1);
|
||||
ASSERT_EQ(sut.GetIndexAndIncrement(), 1);
|
||||
ASSERT_EQ(sut.GetIndex(), 2);
|
||||
}
|
||||
|
||||
TEST(RotatingIndex, TestReset) {
|
||||
RotatingIndex<int> sut(4);
|
||||
|
||||
sut.GetIndexAndIncrement();
|
||||
sut.ResetIndex();
|
||||
ASSERT_EQ(sut.GetIndex(), 0);
|
||||
}
|
||||
|
||||
TEST(RotatingIndex, TestDifferentTypeAndMaximum) {
|
||||
RotatingIndex<short> sut(6);
|
||||
|
||||
ASSERT_FALSE(sut.IncrementAndCheckIfRevolves());
|
||||
ASSERT_FALSE(sut.IncrementAndCheckIfRevolves());
|
||||
ASSERT_FALSE(sut.IncrementAndCheckIfRevolves());
|
||||
ASSERT_FALSE(sut.IncrementAndCheckIfRevolves());
|
||||
ASSERT_FALSE(sut.IncrementAndCheckIfRevolves());
|
||||
ASSERT_TRUE(sut.IncrementAndCheckIfRevolves());
|
||||
ASSERT_FALSE(sut.IncrementAndCheckIfRevolves());
|
||||
ASSERT_FALSE(sut.IncrementAndCheckIfRevolves());
|
||||
}
|
||||
Reference in New Issue
Block a user