1 | /*
|
2 | *
|
3 | *
|
4 | Modbus RTU Server Solarheizungsansteuerung
|
5 |
|
6 | ACHTUNG: Library ArduinoModbus wurde aus dem Github Repo gezogen, um int poll() zu benutzen!!
|
7 | Version ist weiterhin 1.0.6...
|
8 |
|
9 | Dieser Sketch erlaubt einen Modbuszugriff auf die Solarsteurungskomponenten
|
10 | Circuit:
|
11 | Arduino NANO
|
12 | 9600Bd
|
13 | AVR ISP- Old Bootloader
|
14 |
|
15 | Nano Layout
|
16 | #--------------------------#
|
17 | 1 TXD Vin Netzteil 6V
|
18 | 0 RXD GND GND
|
19 | Res Res
|
20 | GND 5V 5V Platine
|
21 | Ppe IST 2 D2 ADC7
|
22 | 3 D3 ADC6
|
23 | DE RS485 4 D4 ADC5 19 Licht
|
24 | Ppe Soll 5 D5 ADC4 18 Temp4
|
25 | 6 D6 ADC3 17 Temp3
|
26 | 7 D7 ADC2 16 Temp2
|
27 | 3Wege 8 D8 ADC1 15 Temp1
|
28 | Ppe 9 D9 ADC0 14 Temp0
|
29 | 10 D10 AREF
|
30 | 11 D11 3V3
|
31 | 12 D12 PB5 13
|
32 | #--------------------------#
|
33 | Modbus Register Settings (Arduino Start 30000, PC= 30001=
|
34 | 30000 Temp1 (Factor 10)
|
35 | 30001 Temp2
|
36 | 30002 Temp3
|
37 | 30003 Temp4
|
38 | 30004 Temp5 oder bei V3: Fuellstand
|
39 | 30005 Licht (nur in V3)
|
40 | 30006 3Wegeventil, 0 = Off, 1 = ON (nur in V2)
|
41 | 30007 Pumpe (0=off, 1=ON (nur in V2)
|
42 | 30008 Pumpe Istwert in Watt (nur in V2)
|
43 | 30009 Pumpe Sollwert (0-100%) (nur in V2)
|
44 |
|
45 | Onewire
|
46 | Pin Func Sensore
|
47 | 14 A0 Temp Placa Vorlauf
|
48 | 15 A1 Temp Place Rücklauf
|
49 | 16 A2 Temp Placa Fläche oder Aussen
|
50 | 17 A3 Temp Speicher
|
51 | 18 A4 Temp Fussboden
|
52 | 19 A5 Temp 6 Reserve
|
53 |
|
54 | */
|
55 | //---------------------------------------------------------------------------------
|
56 | // Verschiedene Versionen Kompilieren!!
|
57 | // V2 = 5x Temp, 1xLicht, 2 Relais, PWM SIgnale, Modbusadr 4
|
58 | // V3 = 2xTemp, 1xLicht, 1xFüllstand, Modbusadr 5
|
59 | // V4 = 2xTemp, Modbusadr 6
|
60 | #define FirmwareVersion2
|
61 | //---------------------------------------------------------------------------------
|
62 |
|
63 |
|
64 |
|
65 | //---------------------------------------------------------------------------------
|
66 | //RS485 Library
|
67 | #include <ArduinoRS485.h> // ArduinoModbus depends on the ArduinoRS485 library
|
68 | #include <ArduinoModbus.h>
|
69 | //ONEWIRE
|
70 | #include <OneWire.h>
|
71 | #include <DallasTemperature.h>
|
72 | //#include "filter.h"
|
73 |
|
74 | //---------------------------------------------------------------------------------
|
75 | //Global Const und Vars
|
76 | #define IO_Wegeventil 8
|
77 | #define IO_Pumpe 9
|
78 | #define IO_D5 5
|
79 | #ifdef FirmwareVersion2
|
80 | #define IO_Licht 19
|
81 | #endif
|
82 | #ifdef FirmwareVersion3
|
83 | #define IO_Licht 17
|
84 | #define IO_Fuellstand 16
|
85 | #endif
|
86 | #define IO_D2 2
|
87 |
|
88 |
|
89 |
|
90 | //Modbus
|
91 | #define numCoils 0
|
92 | #define numDiscreteInputs 0
|
93 | #define numHoldingRegisters 10
|
94 | #define numInputRegisters 0
|
95 | #ifdef FirmwareVersion2
|
96 | #define Modbusadress 4
|
97 | #endif
|
98 | #ifdef FirmwareVersion3
|
99 | #define Modbusadress 5
|
100 | #endif
|
101 | #ifdef FirmwareVersion4
|
102 | #define Modbusadress 6
|
103 | #endif
|
104 |
|
105 | //Dallas TempSensoren
|
106 | OneWire ds18x201(14);
|
107 | OneWire ds18x202(15);
|
108 | #ifdef FirmwareVersion2
|
109 | OneWire ds18x203(16);
|
110 | OneWire ds18x204(17);
|
111 | OneWire ds18x205(18);
|
112 | #endif
|
113 |
|
114 | #define oneWireCount 5
|
115 | DallasTemperature sensor[oneWireCount];
|
116 |
|
117 | //Check if Master still connected
|
118 | unsigned long period = 60000;
|
119 | unsigned long time_now = 0;
|
120 |
|
121 | unsigned int pwmsoll = 0;
|
122 | unsigned long PpeHightime = 0;
|
123 | unsigned long PpeLowtime = 0;
|
124 | int TmpInt = 0;
|
125 | float TmpFloat = 0.0;
|
126 | float T1_Current = 0;
|
127 | float T2_Current = 0;
|
128 | float T3_Current = 0;
|
129 | float T4_Current = 0;
|
130 | float T5_Current = 0;
|
131 | float TLicht_Current = 0;
|
132 | float TFuell_Current =0;
|
133 |
|
134 | //---------------------------------------------------------------------------------
|
135 | void setup() {
|
136 | //Serial.begin(9600);
|
137 | //while (!Serial);
|
138 | #ifdef FirmwareVersion2
|
139 | pinMode(IO_Wegeventil, OUTPUT); //Relais für Pumpe EIN
|
140 | pinMode(IO_Pumpe, OUTPUT); //Relais für 3Wegeventil
|
141 | digitalWrite(IO_Wegeventil,1); // Relais abschalten
|
142 | digitalWrite(IO_Pumpe,1);
|
143 | pinMode(IO_Licht,INPUT); //Lichtsensor A6
|
144 | #endif
|
145 | #ifdef FirmwareVersion3
|
146 | pinMode(IO_Licht,INPUT); //Lichtsensor A6
|
147 | pinMode(IO_Fuellstand,INPUT); //Lichtsensor A6
|
148 |
|
149 | #endif
|
150 | pinMode(LED_BUILTIN, OUTPUT);
|
151 | analogReference(DEFAULT);
|
152 |
|
153 | digitalWrite(LED_BUILTIN,HIGH);
|
154 | //Die RX,TX und Richtungspins setzen
|
155 | RS485.setPins(0,1,4);
|
156 |
|
157 | // start the Modbus RTU server, with (slave) id
|
158 | if (!ModbusRTUServer.begin(Modbusadress, 9600)) {
|
159 | while (1);
|
160 | }
|
161 | ModbusRTUServer.configureHoldingRegisters(30000, numHoldingRegisters);
|
162 |
|
163 | //Onewire SETUP
|
164 | // Start up the library on all defined bus-wires
|
165 | DeviceAddress deviceAddress;
|
166 | sensor[0].setOneWire(&ds18x201);
|
167 | sensor[0].begin();
|
168 | if (sensor[0].getAddress(deviceAddress, 0)){
|
169 | sensor[0].setResolution(deviceAddress, 9);
|
170 | sensor[0].setWaitForConversion(false);
|
171 | }
|
172 | sensor[1].setOneWire(&ds18x202);
|
173 | sensor[1].begin();
|
174 | if (sensor[1].getAddress(deviceAddress, 0)){
|
175 | sensor[1].setResolution(deviceAddress, 9);
|
176 | sensor[1].setWaitForConversion(false);
|
177 | }
|
178 | #ifdef FirmwareVersion2
|
179 | sensor[2].setOneWire(&ds18x203);
|
180 | sensor[2].begin();
|
181 | if (sensor[2].getAddress(deviceAddress, 0)){
|
182 | sensor[2].setResolution(deviceAddress, 9);
|
183 | sensor[2].setWaitForConversion(false);
|
184 | }
|
185 | sensor[3].setOneWire(&ds18x204);
|
186 | sensor[3].begin();
|
187 | if (sensor[3].getAddress(deviceAddress, 0)){
|
188 | sensor[3].setResolution(deviceAddress, 9);
|
189 | sensor[3].setWaitForConversion(false);
|
190 | }
|
191 | sensor[4].setOneWire(&ds18x205);
|
192 | sensor[4].begin();
|
193 | if (sensor[4].getAddress(deviceAddress, 0)) {
|
194 | sensor[4].setResolution(deviceAddress, 9);
|
195 | sensor[4].setWaitForConversion(false);
|
196 | }
|
197 | #endif
|
198 |
|
199 | ModbusRTUServer.holdingRegisterWrite(30000,0);
|
200 | ModbusRTUServer.holdingRegisterWrite(30001,0);
|
201 | ModbusRTUServer.holdingRegisterWrite(30002,0);
|
202 | ModbusRTUServer.holdingRegisterWrite(30003,0);
|
203 | ModbusRTUServer.holdingRegisterWrite(30004,0);
|
204 | ModbusRTUServer.holdingRegisterWrite(30005,0);
|
205 | ModbusRTUServer.holdingRegisterWrite(30006,0);
|
206 | ModbusRTUServer.holdingRegisterWrite(30007,0);
|
207 | ModbusRTUServer.holdingRegisterWrite(30008,0);
|
208 | ModbusRTUServer.holdingRegisterWrite(30009,0);
|
209 | digitalWrite(LED_BUILTIN,LOW);
|
210 | }
|
211 |
|
212 | //---------------------------------------------------------------------------------
|
213 |
|
214 | //---------------------------------------------------------------------------------
|
215 | void loop() {
|
216 | // Sicherheitslogik: Fällt der master aus, dann eigensicherer Zustand
|
217 | if (ModbusRTUServer.poll() ==1 ){
|
218 | time_now = millis();
|
219 | } else {
|
220 | if((unsigned long)(millis() - time_now) > period){
|
221 | ModbusRTUServer.holdingRegisterWrite(30009,0);
|
222 | ModbusRTUServer.holdingRegisterWrite(30008,0);
|
223 | ModbusRTUServer.holdingRegisterWrite(30007,0);
|
224 | ModbusRTUServer.holdingRegisterWrite(30006,0);
|
225 | }
|
226 | }
|
227 |
|
228 | //5 Temperaturen einlesen
|
229 | if (sensor[0].getDS18Count() >0) {
|
230 | sensor[0].requestTemperatures();
|
231 | }
|
232 | if (sensor[1].getDS18Count() >0) {
|
233 | sensor[1].requestTemperatures();
|
234 | }
|
235 | #ifdef FirmwareVersion2
|
236 | if (sensor[2].getDS18Count() >0) {
|
237 | sensor[2].requestTemperatures();
|
238 | }
|
239 | if (sensor[3].getDS18Count() >0) {
|
240 | sensor[3].requestTemperatures();
|
241 | }
|
242 | if (sensor[4].getDS18Count() >0) {
|
243 | sensor[4].requestTemperatures();
|
244 | }
|
245 | #endif
|
246 | delay(200);
|
247 | if (sensor[0].getDS18Count() >0) {
|
248 | TmpFloat = sensor[0].getTempCByIndex(0);
|
249 | T1_Current = (0.1 * TmpFloat) + (0.9) * T1_Current;
|
250 | TmpInt = int(T1_Current*10);
|
251 | ModbusRTUServer.holdingRegisterWrite(30000,TmpInt);
|
252 | }
|
253 | if (sensor[1].getDS18Count() >0) {
|
254 | TmpFloat = sensor[1].getTempCByIndex(0);
|
255 | T2_Current = (0.1 * TmpFloat) + (0.9 * T2_Current);
|
256 | TmpInt = int(T2_Current*10 );
|
257 | ModbusRTUServer.holdingRegisterWrite(30001,TmpInt);
|
258 |
|
259 | }
|
260 | #ifdef FirmwareVersion2
|
261 | if (sensor[2].getDS18Count() >0) {
|
262 | TmpFloat = sensor[2].getTempCByIndex(0);
|
263 | T3_Current = (0.1 * TmpFloat) + (0.9 * T3_Current);
|
264 | TmpInt = int(T3_Current*10 );
|
265 | ModbusRTUServer.holdingRegisterWrite(30002,TmpInt);
|
266 | }
|
267 | if (sensor[3].getDS18Count() >0) {
|
268 | TmpFloat = sensor[3].getTempCByIndex(0);
|
269 | T4_Current = (0.1 * TmpFloat) + (0.9 * T4_Current);
|
270 | TmpInt = int(T4_Current*10 );
|
271 | ModbusRTUServer.holdingRegisterWrite(30003,TmpInt );
|
272 | }
|
273 | if (sensor[4].getDS18Count() >0) {
|
274 | TmpFloat = sensor[4].getTempCByIndex(0);
|
275 | T5_Current = (0.1 * TmpFloat) + (0.9 * T5_Current);
|
276 | TmpInt = int(T5_Current*10 );
|
277 | ModbusRTUServer.holdingRegisterWrite(30004,TmpInt );
|
278 | }
|
279 | #endif
|
280 |
|
281 | //Pumpe Sollwert setzen
|
282 | #ifdef FirmwareVersion2
|
283 | pwmsoll = ModbusRTUServer.holdingRegisterRead(30009);
|
284 | if (ModbusRTUServer.holdingRegisterRead(30007) == 1){
|
285 | digitalWrite(IO_Pumpe,0);
|
286 | if (pwmsoll <=100) {
|
287 | TmpInt = int(2.55*(100-pwmsoll));
|
288 | analogWrite(IO_D5,TmpInt);
|
289 | }//if pwm
|
290 | } else {
|
291 | analogWrite(IO_D5,0);
|
292 | digitalWrite(IO_Pumpe,1);
|
293 | //ModbusRTUServer.holdingRegisterWrite(30009,0);
|
294 | }
|
295 | #endif
|
296 | #ifdef FirmwareVersion2
|
297 | //Istwert der Pumpe auslesen
|
298 | PpeHightime = pulseIn(IO_D2, HIGH, 60000); //Pin, High oder LOW messen, Timeout in µs
|
299 | PpeLowtime = pulseIn(IO_D2, LOW, 60000); //Pin, High oder LOW messen, Timeout in µs
|
300 | //pulsein liefert 0 wenn kein Signal gemessen wurde, sonst µs Dauer
|
301 | if (PpeHightime+PpeLowtime > 0){
|
302 | //d% der Pumpe berechnen d%= 100* (t/T) t=hightime, T=75Hz(ca.13ms)
|
303 | //Bsp: 50% -> 75Hz=13300µs PpeHightime = 6650µs, PpeLowTime= 6650µs,
|
304 | //6650*100 / 6650+6650 = 50
|
305 | TmpInt = (PpeHightime *100)/(PpeHightime+PpeLowtime);
|
306 | ModbusRTUServer.holdingRegisterWrite(30008,TmpInt);
|
307 | } else {
|
308 | //Keine Rückmeldung der ppe, Wert ist 0
|
309 | ModbusRTUServer.holdingRegisterWrite(30008,0);
|
310 | }
|
311 | #endif
|
312 | #ifdef FirmwareVersion2
|
313 | //3Wegeventil EIN/AUS
|
314 | if (ModbusRTUServer.holdingRegisterRead(30006) == 1){
|
315 | digitalWrite(IO_Wegeventil,0);
|
316 | } else {
|
317 | digitalWrite(IO_Wegeventil,1);
|
318 | }
|
319 | #endif
|
320 |
|
321 | #if defined(FirmwareVersion2) || defined(FirmwareVersion3)
|
322 | //Lichtsonsor abfragen
|
323 | TmpInt = analogRead(IO_Licht);
|
324 | TLicht_Current = (0.1 * TmpInt) + (0.9 * TLicht_Current);
|
325 | TmpInt = int(TLicht_Current );
|
326 | ModbusRTUServer.holdingRegisterWrite(30005,TmpInt);
|
327 | #endif
|
328 |
|
329 | #ifdef FirmwareVersion3
|
330 | //Füllstand abfragen
|
331 | TmpInt = analogRead(IO_Fuellstand);
|
332 | TFuell_Current = (0.1 * TmpInt) + (0.9 * TFuell_Current);
|
333 | TmpInt = int(TFuell_Current );
|
334 | ModbusRTUServer.holdingRegisterWrite(30004,TmpInt);
|
335 | #endif
|
336 |
|
337 | }//Loop
|
338 | //END END END
|