From 42e49ce2892b41e687c9a6a0dbc9b8c7f674d3c8 Mon Sep 17 00:00:00 2001 From: chschloetel Date: Fri, 1 Nov 2024 21:51:43 +0100 Subject: [PATCH] Create Project --- .gitignore | 5 + .vscode/extensions.json | 10 ++ fritzing_sketch.fzz | Bin 0 -> 11453 bytes include/GPIO.cpp | 36 ++++++ include/GPIO.h | 19 ++++ include/README | 39 +++++++ lib/ModbusSlaveConfigToEEPROM.h | 42 +++++++ lib/README | 46 ++++++++ platformio.ini | 28 +++++ src/main.cpp | 194 ++++++++++++++++++++++++++++++++ test/README | 11 ++ 11 files changed, 430 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 fritzing_sketch.fzz create mode 100644 include/GPIO.cpp create mode 100644 include/GPIO.h create mode 100644 include/README create mode 100644 lib/ModbusSlaveConfigToEEPROM.h create mode 100644 lib/README 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/fritzing_sketch.fzz b/fritzing_sketch.fzz new file mode 100644 index 0000000000000000000000000000000000000000..3845870e0140b4753ba2cad62a3c4ed78666c30b GIT binary patch literal 11453 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 S)g$0v5_q=(9#Td@`F{ZMRV)?& literal 0 HcmV?d00001 diff --git a/include/GPIO.cpp b/include/GPIO.cpp new file mode 100644 index 0000000..8e3e8f8 --- /dev/null +++ b/include/GPIO.cpp @@ -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); +} diff --git a/include/GPIO.h b/include/GPIO.h new file mode 100644 index 0000000..e18c0a7 --- /dev/null +++ b/include/GPIO.h @@ -0,0 +1,19 @@ +#ifndef GPIO_h +#define GPIO_h + + +#include + +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 \ 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/ModbusSlaveConfigToEEPROM.h b/lib/ModbusSlaveConfigToEEPROM.h new file mode 100644 index 0000000..ace6470 --- /dev/null +++ b/lib/ModbusSlaveConfigToEEPROM.h @@ -0,0 +1,42 @@ +#ifndef ModbusSlaveConfigToEEPROM_H +#define ModbusSlaveConfigToEEPROM_H +#include +#include + +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 \ 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/platformio.ini b/platformio.ini new file mode 100644 index 0000000..47d7265 --- /dev/null +++ b/platformio.ini @@ -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 diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..f3eba33 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,194 @@ +#include +#include +#include +#include +#include + +// 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); + // } +} 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