Create Project

This commit is contained in:
chschloetel 2024-11-01 21:51:43 +01:00
commit 42e49ce289
11 changed files with 430 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"
]
}

BIN
fritzing_sketch.fzz Normal file

Binary file not shown.

36
include/GPIO.cpp Normal file
View File

@ -0,0 +1,36 @@
#include "GPIO.h"
// Konstruktor ( Quasi das Setup in einer Arduino.cpp - für jedes Objekt einzeln)
IO::IO(byte pin, bool input) {
this->GPIOPin = pin;
this->GPIOinput = input;
if (this->GPIOinput == false){
pinMode(this->GPIOPin, OUTPUT);
} else {
pinMode(this->GPIOPin, INPUT);
}
}
byte IO::SetHigh() {
digitalWrite(this->GPIOPin, HIGH);
if (this->GetState() == HIGH){
return 100;
} else {
return 200;
}
}
byte IO::SetLow() {
digitalWrite(this->GPIOPin, LOW);
if (this->GetState() == LOW){
return 101;
} else {
return 201;
}
}
byte IO::GetState() {
return digitalRead(this->GPIOPin);
}

19
include/GPIO.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef GPIO_h
#define GPIO_h
#include <Arduino.h>
class IO {
private:
byte GPIOPin; // byte heißt 0-255 = 8 Bit
bool GPIOinput;
public:
IO(byte pin, bool input);
byte SetHigh();
byte SetLow();
byte GetState();
};
#endif

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,42 @@
#ifndef ModbusSlaveConfigToEEPROM_H
#define ModbusSlaveConfigToEEPROM_H
#include <Arduino.h>
#include <EEPROM.h>
class ModBusConfig{
public:
ModBusConfig(int ID, int BAUDRATE);
void SetModbusID(int ID);
void SetBaudRate(int BAUDRATE);
int GetModbusID();
int GetBaudRate();
private:
int ModBusID;
int ModBusBaudrate;
};
void ModBusConfig::SetModbusID(int BAUDRATE){
EEPROM.write(0,BAUDRATE);
}
void ModBusConfig::SetBaudRate(int BAUDRATE){
// divide Baudrate / 100 - to save it in Eeprom (8Bit 0 - 255)
int dividedBaudrate = BAUDRATE/100;
if ( dividedBaudrate != EEPROM.read(1)){
EEPROM.write(1,dividedBaudrate);
}
}
int ModBusConfig::GetModbusID(){
return EEPROM.read(0);
}
int ModBusConfig::GetBaudRate(){
int Baudrate = EEPROM.read(1)*100;
return Baudrate;
}
#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

28
platformio.ini Normal file
View File

@ -0,0 +1,28 @@
; 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:pro16MHzatmega328]
platform = atmelavr
board = pro16MHzatmega328
framework = arduino
lib_deps =
yaacov/ModbusSlave@^2.1.1
robtillaart/SHT2x@^0.3.0
upload_port = COM4
; [env:esp32devkitv4]
; platform = espressif32
; board = az-delivery-devkit-v4
; framework = arduino
; upload_port = COM4
; upload_speed = 115200
; lib_deps =
; yaacov/ModbusSlave@^2.1.1
; robtillaart/SHT2x@^0.3.0

194
src/main.cpp Normal file
View File

@ -0,0 +1,194 @@
#include <Arduino.h>
#include <Wire.h>
#include <ModbusSlave.h>
#include <EEPROM.h>
#include <SHT2x.h>
// ID und Baudrate sollten zukünftig im EEPROM hinterlegt sein.
#define SLAVE_ID 8 // The Modbus slave ID, change to the ID you want to use.
#define SERIAL_BAUDRATERS485 9600 // Change to the baudrate you want to use for Modbus communication.
#define SERIAL_PORTRS485 Serial // Serial port to use for RS485 communication, change to the port you're using.
// Comment out the following line if your not using RS485
#define RS485_CTRL_PIN 8 // Change to the pin the RE/DE pin of the RS485 controller is connected to.
#define OutPutPin 9
// The position in the array determines the address. Position 0 will correspond to Coil, Discrete input or Input register 0.
uint8_t ReadCoilRegister[] = {0, 1, 2}; // Add the registers for DigitalPins or else.
uint8_t output_pins[] = {0,1}; // Add the registers for Controlling Outputs
uint8_t ReadInputRegister[] = {0,1,2,3,4,5,6,7}; // Add the registers for Sensors /Light Temp etc.
// You shouldn't have to change anything below this to get this example to work
uint8_t ReadCoilRegister_size = sizeof(ReadCoilRegister) / sizeof(ReadCoilRegister[0]); // Get the size of the ReadCoilRegister array
uint8_t output_pins_size = sizeof(output_pins) / sizeof(output_pins[0]); // Get the size of the output_pins array
uint8_t ReadInputRegister_size = sizeof(ReadInputRegister) / sizeof(ReadInputRegister[0]); // Get the size of the ReadInputRegister array
int ValueInputOne = 0;
#ifdef RS485_CTRL_PIN
// Modbus object declaration
Modbus slave(SERIAL_PORTRS485, SLAVE_ID, RS485_CTRL_PIN);
#else
Modbus slave(SERIAL_PORTRS485, SLAVE_ID);
#endif
//SHT2x //SHT21EnvSensor;
// Modbus handler functions
// The handler functions must return an uint8_t and take the following parameters:
// uint8_t fc - function code
// uint16_t address - first register/coil address
// uint16_t length/status - length of data / coil status
// Handle the function codes Force Single Coil (FC=05) and Force Multiple Coils (FC=15) and set the corresponding digital output pins (coils).
uint8_t writeDigitalOut(uint8_t fc, uint16_t address, uint16_t length)
{
// Check if the requested addresses exist in the array
if (address > output_pins_size || (address + length) > output_pins_size)
{
return STATUS_ILLEGAL_DATA_ADDRESS;
}
// // Set the output pins to the given state.
for (uint16_t i = 0; i < length; i++)
{
// Write the value in the input buffer to the digital pin.
if (i == 0)
{
if (slave.readCoilFromBuffer(i) == 1){
digitalWrite(OutPutPin,HIGH);
} else {
digitalWrite(OutPutPin,LOW);
}
}
}
return STATUS_OK;
}
// Handle the function code Read Input Status (FC=02) and write back the values from the digital input pins (discreet input).
uint8_t fReadCoilRegister(uint8_t fc, uint16_t address, uint16_t length)
{
// Check if the requested addresses exist in the array
if (address > ReadCoilRegister_size || (address + length) > ReadCoilRegister_size)
{
return STATUS_ILLEGAL_DATA_ADDRESS;
}
// Read the digital inputs.
for (uint16_t i = 0; i < length; i++)
{
// Write the state of the digital pin to the response buffer.
if (i == 0) {
slave.writeCoilToBuffer(i, digitalRead(OutPutPin));
}
if (i == 1) {
slave.writeCoilToBuffer(i, 0);
}
if (i == 2) {
slave.writeCoilToBuffer(i, 1);
}
}
return STATUS_OK;
}
// Handle the function code Read Input Registers (FC=04) and write back the values from analog input pins (input registers).
uint8_t fReadInputRegister(uint8_t fc, uint16_t address, uint16_t length)
{
// Check if the requested addresses exist in the array
if (address > ReadInputRegister_size || (address + length) > ReadInputRegister_size)
{
return STATUS_ILLEGAL_DATA_ADDRESS;
}
// Read the inputs
for (uint16_t i = 0; i < length; i++)
{
// Write the state of the analog pin to the response buffer.
slave.writeRegisterToBuffer(i, analogRead(ReadInputRegister[address + i]));
float temperatur = 21.21;//SHT21EnvSensor.getTemperature();
float humidity = 55.55;//SHT21EnvSensor.getHumidity();
if (i == 0){
slave.writeRegisterToBuffer(i, millis()/1000); // = Minuten
}
if (i == 1){
slave.writeRegisterToBuffer(i, SERIAL_BAUDRATERS485);
}
if (i == 2){
slave.writeRegisterToBuffer(i, SLAVE_ID);
}
if (i == 3){
////SHT21EnvSensor.read();
//float temperatur = //SHT21EnvSensor.getTemperature()*100;
float temp_temperatur = temperatur*100;
slave.writeRegisterToBuffer(i, (int)temp_temperatur);
}
if (i == 4){
////SHT21EnvSensor.read();
//float humidity = //SHT21EnvSensor.getHumidity()*100;
float humidity = 55.55;
float temp_humidity = humidity*100;
slave.writeRegisterToBuffer(i, (int)temp_humidity);
}
if (i == 5){
const double UG = 8314.3; // J/(kmol*K) (universelle Gaskonstante)
const double mw = 18.016; // kg/kmol (Molekulargewicht des Wasserdampfes)
const double K = 273.15; // °K (Entspricht 0°K)
const double tp = 6.1078; // hPa Triplettpunkt von Wasser bei 0,01°C
double absolutHumidity = (100000 * mw / UG * humidity / 100 * tp * pow(10, ((7.5 * temperatur) / (239 + temperatur))) / (temperatur + K))*100;
slave.writeRegisterToBuffer(i, (int)absolutHumidity);
}
if (i == 6){
slave.writeRegisterToBuffer(i, 5); // Später für Rückgabe Helligkeit
}
if (i == 7){
slave.writeRegisterToBuffer(i, digitalRead(OutPutPin)); // Später für Rückgabe Helligkeit
}
}
return STATUS_OK;
}
void setup()
{
pinMode(8, OUTPUT);
// Register functions to call when a certain function code is received.
//slave.cbVector[CB_WRITE_COILS] = writeDigitalOut;
slave.cbVector[CB_READ_DISCRETE_INPUTS] = fReadCoilRegister;
slave.cbVector[CB_READ_INPUT_REGISTERS] = fReadInputRegister;
slave.cbVector[CB_WRITE_COILS] = writeDigitalOut;
// Set the serial port and slave to the given baudrate.
SERIAL_PORTRS485.begin(SERIAL_BAUDRATERS485);
slave.begin(SERIAL_BAUDRATERS485);
//SHT21EnvSensor.begin();
//SHT21EnvSensor.read();
//Serial.begin(115200);
//Serial.printf("Start Modbus-Server");
pinMode(OutPutPin,OUTPUT);
digitalWrite(OutPutPin,LOW);
}
void loop()
{
// Listen for modbus requests on the serial port.
// When a request is received it's going to get validated.
// And if there is a function registered to the received function code, this function will be executed.
slave.poll();
// if (ValueInputOne == 100) {
// digitalWrite(OutPutPin,HIGH);
// } else {
// digitalWrite(OutPutPin,LOW);
// }
}

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