Help with modbusrtu

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301


#include "ModbusRTU.hpp"
#include <iostream>

ModbusRTU::ModbusRTU (uint8_t id) : _DO(20), _AO(10) {
  
  _id = id;
  
  for(unsigned i = 0; i< _DO.size(); i += 2)
    _DO[i] = true;
    
  for(unsigned i = 0; i< _AO.size(); i++)
    _AO[i] = i * 4;
    
    
}

Mensaje ModbusRTU::peticion(Mensaje recibido) {
  
  Mensaje respuesta;

  std::cerr << "Recibido mensaje " <<recibido.toString() << std::endl;

  uint8_t id = recibido[0];
  uint8_t funcion = recibido[1];
  
  std::cerr << "El mensaje es para " << (int)id
      << " y la funcion es " << (int)funcion << std::endl;
  
  
  //Parte3 ahi nene
  if(id !=_id) { 
    return respuesta;
  }
  if(!recibido.crcOK()==true){
      return respuesta;
  }
    
  
  
  
  
  
  
  switch(funcion) {
  case 3:
    respuesta = atiende03(recibido);
    break;
    
  case 1:
    respuesta = atiende01(recibido);
    break;
    
  case 5:
    respuesta = atiende05(recibido);
    break;
    
  case 15:
    respuesta = atiende15(recibido);
    break;
    
  case 6:
    respuesta = atiende06(recibido);
    break;
    
  case 16:
    respuesta = atiende16(recibido);
    break;
    
    
  default:
    std::cerr << "Funcion aún no implementada" << std::endl;
    
 
  respuesta.push_back(recibido[0]);
  respuesta.push_back(recibido[1] | (1<<7));
  respuesta.push_back(01);
  respuesta.aniadeCRC();
  }
  

  
  
  
  return respuesta;
}

Mensaje ModbusRTU::atiende03(Mensaje recibido) {
  Mensaje respuesta;
    std::cerr << "Entramos en método atiende03 con mensaje "
      << recibido.toString() << std::endl;

  
 return respuesta; 
}
        
      
      
      
unsigned offset = recibido.getWordAt(2);
unsigned numPos = recibido.getWordAt(4);


  
  return respuesta;
  
  
  
  }
  respuesta.push_back(recibido[0]); //Id
  respuesta.push_back(recibido[1]); //funcion
  respuesta.push_back((2* numPos));

  
  for(unsigned i = offset; i < (offset + numPos) ; i++) {
    std::cerr << "Accediendo AO[" << i <<"]: " << _AO[i] << std::endl;
    respuesta.pushWord_back(_AO[i]);
    //videoparte4 minuto 15:27
  
  
  }
  
  respuesta.aniadeCRC();
  
  
  return respuesta;
}



Mensaje ModbusRTU::atiende01(Mensaje recibido) {
  Mensaje respuesta;
  std::cerr << "Entramos en método atiende01 con mensaje "
      << recibido.toString() << std::endl;
      


  unsigned offset = recibido.getWordAt(2);
  unsigned numPos = recibido.getWordAt(4);
  
   if((offset+numPos) > (_DO.size())){
    
  respuesta.push_back(recibido[0]); //Id
  //respuesta.push_back(recibido[1]); //funcion
  uint8_t error=2;
  respuesta.push_back(recibido[1] | (1<<7));
  respuesta.push_back(error);
  respuesta.aniadeCRC();
  
  
  return respuesta;
  }
  respuesta.push_back(recibido[0]); //Id
  respuesta.push_back(recibido[1]); //funcion
   
  unsigned numBytes = ((numPos - 1)/ 8) + 1;
  
  respuesta.push_back(numBytes);
  
  unsigned posBit = 0;
  uint8_t dato = 0;
  for(unsigned p = offset; p < (offset + numPos); p++) {
    std::cerr << "Accediendo DO[" << p <<"]: " << _DO[p] << std::endl;
    if (_DO[p]){
      dato = dato | (1 <<posBit);
      
    }
    posBit++;
    if(posBit == 8){ //hemos rellenado un byte
      
      respuesta.push_back(dato);
      dato=0;
      posBit=0;
  }
    
}
  if(posBit > 0) {//byte a medio rellenar
    
    respuesta.push_back(dato);
    
     }
  respuesta.aniadeCRC();
  
  
  
 
  
  return respuesta;
}
Mensaje ModbusRTU::atiende05(Mensaje recibido) {
  Mensaje respuesta;
  
  std::cerr << "Entramos en método atiende05 con mensaje "
      << recibido.toString() << std::endl;

  
  
 return respuesta; 
}

 unsigned offset = recibido.getWordAt(2);
  

 
  if ( (recibido[4] == 0xFF) && (recibido[5] == 0x00) ){
    _DO[offset] = true;
    std::cerr << "Ponemos a 1 la DO[" << offset <<"]: " << _DO[offset] 
        << std::endl;

    
  } else if ( (recibido[4] == 0x00) && (recibido[5] == 0x00) ){
    _DO[offset] = false;
    std::cerr << "Ponemos a 0 la DO[" << offset <<"]: " << _DO[offset] 
        << std::endl;

  } 
  
 return respuesta; 
  
  }
  
  
return recibido;  

}

Mensaje ModbusRTU::atiende15(Mensaje recibido) {
Mensaje respuesta;

std::cerr << "Entramos en método atiende15 con mensaje " //mensaje depuración
<< recibido.toString() << std::endl;




//respuesta.push_back(recibido[1]); //funcion

uint16_t offset = recibido.getWordAt(2); //representa offset
uint16_t numPos = recibido.getWordAt(4);
unsigned nDatos = recibido.getWordAt(6);


respuesta.push_back(recibido[0]); //Id
respuesta.push_back(recibido[1]); //funcion

respuesta.pushWord_back(offset); //usamos pushWord porque son dos bytes y lo
//añadimos en la respuesta
respuesta.pushWord_back(numPos);
Mensaje datos; //variable para guardar valores

int valorDatos = 7; //indice de primer dato



for( unsigned i=0; i < nDatos; i++ ) {
//recorremos la variable y guardamos los valores que encontramos
datos.push_back(recibido[valorDatos]);

valorDatos++;
}

int bit = 0; //inicializamos los valores en 0
int byte = 0;

for(unsigned i = offset; i < (offset + numPos); i++) {
std::cerr << "Accediendo DO[" << i << "]: " << _DO[i] << std::endl;

if ((datos[byte]) & (1<< bit)) { //creamos una máscara para recorrer los bits
// de un registro
_DO[i] = true; //ponemos a 1 esa posición cuando se cumpla la
// condición si no lo pone a 0

}else{

_DO[i] = false;
}
bit++; //cuando entre en cualquiera de los if pasa al
// siguiente bit

if (bit >7) { //cuando ya hayamos completado un byte ponemos bit a cero
//y pasamos al siguiente byte
bit = 0;
byte++;
}


}



respuesta.aniadeCRC();


return respuesta;
}
   
 


Hello tumbalacasa,

Your code needs proper indenting because it is hard to read.

I do not know at the moment if this will make any difference, but personally I would reverse lines 3 and 4.

Your subject says Help with modbusrtu. There are many member functions of the class posted that start with ModbusRTU, so which one is the problem?

It would also help if you poster the ModbusRTU.hpp code so that everyone can see what you have done. It is possible that the problem starts in the ".hpp" file, but shows up in the ".cpp" file.

Since you are new it is best to add a new message and not change the original post as it can confuse people.

Looking at the code you have posted I see things like _DO and _AO. It is best not to start variable names or function names with an underscore as this could clash with what might be in the include files like "iostream". Best to leave the underscore(s) for the standard header files. Also names like "DO" make me think that this is defined as a constant that can not be changed. Without the class definition I am not sure what you are doing.

Proper indenting and a few less blank lines in some places and a blank line in other places will make the code easier to read.

Andy
I do not know at the moment if this will make any difference, but personally I would reverse lines 3 and 4.

In general, it's good practise to include user-written, higher-level header files first, and lower-level standard library includes afterwards. This makes it easier to check whether you've included everything you need to in your own header files.
Topic archived. No new replies allowed.