howto/come_gestire_comunicazione_rs485/gestione_rs485_con_schede_syel.md
... ...
@@ -0,0 +1,235 @@
1
+La gestione della comunicazione RS485 può essere fatta sfruttando tre tipi di protoccollo:
2
+- Protocollo a **livello di singolo carattere** con buffer di ricezione (è il modo di default all'apertura di una COM)
3
+- Protocollo a **ivello di blocco** (**SYEL BLOCK MODE 1**)
4
+- Protocollo a **livello di funzioni** (**SYEL BLOCK MODE 2**)
5
+
6
+Se la periferica è SYEL, di solito si utilizza il SYEL BLOCK MODE 1.
7
+
8
+Di seguito, un **esempio** sulla gestione della comunicazione RS485 in SYEL BLOCK MODE 1 in cui la centrale invia informazioni sulle operazioni che la periferica deve fare e la periferica risponde in base al pacchetto ricevuto.
9
+
10
+In questo programma la centrale comunica alla periferica:
11
+- quali uscite (1 - 10) attivare/disattivare
12
+- se attivare il pwm sull'uscita 1 (e quanto impostare la frequenza e duty cycle)
13
+- quanto potente (veloce) deve essere l'uscita chiamata pomp (gestita da uno slider grafico)
14
+- richiedere lo stato degli ingressi In e Potenz
15
+
16
+Nel **common.h** (o comunque in un file .h incluso nel common):
17
+
18
+ #define PortaCOM COM2 // definisce PortaCOM (in questo caso è la COM2)
19
+ #define BAUD_RATE 115200 // deifnisce il baud rate della porta COM (in questo caso 115200)
20
+
21
+ // definizione comandi ralativi alla periferica del progetto
22
+ /***************************************
23
+ ;Comando per settate singolo out
24
+ ;0-0-0-3-1-3-'K'(H4B)-dato1=N°CH-dato2=freq.-dato3=pwm. Pwm =0-7 freq= 7sempre on, 6 512mSec, 5 256mSec, 4 128 mSec ecc
25
+ ***************************************/
26
+ #define OUT_ON_OFF 0x4B
27
+
28
+ /***************************************
29
+ ;Comando per settare velocità pompa
30
+ ;0-0-0-3-1-2-'p'(H70)-valore%
31
+ ***************************************/
32
+ #define POMP_VEL 0x70
33
+
34
+ /***************************************
35
+ ;Comando per leggere digitale+analogico
36
+ ;0-0-0-3-1-1-'i' Risposta 1dato digitale+2dato analogico
37
+ ***************************************/
38
+ #define READ_IN 0x69
39
+
40
+
41
+ //---------------------funzioni----------------------
42
+ void init_serial_Rs485(void); // funzione per inizializzare la seriale
43
+ void init_out(void); // funzione per inizializzare lo stato iniziale delle uscite
44
+ void TaskCOM485(void); // funzione principale per la comunicazione seriale 485
45
+ void tx485(void); // funzione per flag del tx della seriale
46
+ void subrx(void); // subroutine per la lettura dei messaggi ricevuti
47
+ void update_bufferTX_out(int); // funzione che aggiorna il buffer con i dati da inviare (bufferTX) relativi alle uscite
48
+ void update_bufferTX_pomp(void); // funzione che aggiorna il buffer con i dati da inviare relativi al settaggio dell' uscita pomp
49
+ void clear_bufferRX(void); // funzione che svuota il buffer in cui vengono salvati i dati arrivati (bufferRX)
50
+
51
+ //--------------------costanti e variabili--------------------
52
+ const int num_centr = 128; // numero della centrale (in questo caso 128)
53
+ const int num_perif = 1; // numero della periferica (in questo caso 1)
54
+ const int dim_bufferTX = 129; // dimensioni massime del buffer con i dati da inviare (bufferTX)
55
+ const int dim_bufferRX = 16; // dimensioni massime del buffer in cui vengono salvati i dati ricevuti (bufferRX)
56
+ const int num_out = 10; // numero totale di uscite
57
+
58
+ volatile U8 bufferTX[dim_bufferTX]; // dichiara il buffer in cui prendere i dati da inviare
59
+ volatile U8 bufferRX[dim_bufferRX]; // dichiara il buffer in cui salvare i dati ricevuti
60
+
61
+ volatile int flag_tx485 = 0; // flag relativa al tx della seriale
62
+
63
+ volatile int flag_out_on_off[num_out]; // flag realtive allo stato delle uscite
64
+ volatile int flag_out_on_off_prec[num_out]; // flag previste realtive allo stato delle uscite
65
+ // (utili per capire quando ha cambiato stato)
66
+
67
+ volatile int flag_pomp_on_off; // flag realtive allo stato dell' uscita pomp
68
+ volatile int flag_pomp_on_off_prec; // flag previste realtive allo stato dell' uscita pomp
69
+
70
+ volatile int flag_pwm_on_off; // flag realtive all' attivazione/disattivazione del pwm sulla prima uscita
71
+ volatile int flag_pwm_on_off_prec; // flag previste realtive all' attivazione/disattivazione del pwm sulla prima uscita
72
+
73
+ volatile short int TXX = 0; // variabile per il conteggio dei pacchetti inviati
74
+ volatile short int RXX = 0; // variabile per il conteggio dei pacchetti ricevuti
75
+
76
+ volatile char In; // prima variabile per lettura ingressi
77
+ volatile char Potenz; // seconda variabile per lettura ingressi
78
+ volatile char freq = 0; // variabile relativa alla frequanza del pwm
79
+ volatile char pwm = 0; // variabile relativa al duty cycle del pwm
80
+ volatile int p; // variabile ralativa al valore % della velocità dell'uscita pomp
81
+
82
+ //-------------------------------------------
83
+ // funzione di inizializzazione seriale RS485
84
+ void init_serial_Rs485(void)
85
+ {
86
+ com_open(PortaCOM, BAUD_RATE); // apre la porta specificando il baud rate
87
+ com_disable(PortaCOM); // disabilita la porta
88
+ protocol_mode(PortaCOM, 1); // imposta il protocollo della seriale su 1 (SYEL BLOCK MODE 1)
89
+ PortaCOM->centr = num_centr; // imposta il numero della centrale
90
+ PortaCOM->perif = num_perif; // imposta il numero della periferica
91
+ onrx(PortaCOM, subrx); // funzione che richiama la subroutine subrx quando ci sono dei dati ricevuti
92
+ com_enable(PortaCOM); // riabilita la porta
93
+ }
94
+
95
+ // subroutine che viene chiamata da onrx quando è arrivato un pacchetto dati
96
+ void subrx(void)
97
+ {
98
+ int n = bload(PortaCOM, bufferRX, 8); // la funzione bload salva il messaggio arrivato, sul bufferRX
99
+ if (n != -1) // se bload restituisce un valore diverso da -1 ha letto correttemente il messaggio
100
+ {
101
+ In = bufferRX[0]; // il valore della variabile In diventa il valore del primo byte del pacchetto
102
+ Potenz = bufferRX[1]; // il valore della variabile Potenz diventa il valore del secondo byte del pacchetto
103
+ RXX++; // incremento del contatore dei pacchetti ricevuti
104
+ }
105
+ clear_bufferRX(); // svuotamento del bufferRX
106
+ }
107
+
108
+ // funzione che inizializza lo stato iniziale delle uscite all' avvio
109
+ void init_out(void)
110
+ {
111
+ // inizializzazione uscite
112
+ for (int i = 0; i < num_out; i++)
113
+ {
114
+ flag_out_on_off[i] = 0; // le flag delle uscite vengono messe tutte a 0 perchè all'avvio sono tutte spente
115
+ flag_out_on_off_prec[i] = 0;
116
+ update_bufferTX_out(i); // agiorna il bufferTX per ogni uscita
117
+ bsave(PortaCOM, bufferTX, 4); // il comando bsave invia i dati contenuti nel bufferTX (comunicando che ogni uscita è spenta)
118
+ wait(10); // aspetta 10 ms per dar tempo di eseguire lo scambio dati
119
+ TXX++; // incremento del contatore dei pacchetti inviati
120
+ }
121
+ flag_pwm_on_off = 0; // la flag del pwm viene messsa a 0 perchè all' avvio il pwm è disattivo
122
+ flag_pwm_on_off_prec = 0;
123
+
124
+ // inizializzazione dell'uscita pomp
125
+ flag_pomp_on_off = 0; // la flag dell' uscita pomp è 0 perchè all' avvio è spenta
126
+ flag_pomp_on_off_prec = 0;
127
+ update_bufferTX_pomp(); // aggiorna il bufferTX con i dati relativi all' uscita pomp
128
+ bsave(PortaCOM, bufferTX, 2); // invia i dati del bufferTX
129
+ wait(10);
130
+ TXX++;
131
+ }
132
+
133
+ // funzione principale per la gestione della comunoicazione RS485 che verrà richiamata nello start.c
134
+ void TaskCOM485(void)
135
+ {
136
+ while(1)
137
+ {
138
+ if (flag_tx485)
139
+ {
140
+ flag_tx485 = 0; // ogni 100 ms (vedi start.c)
141
+
142
+ // controlllo uscite
143
+ for (int i = 0; i < num_out; i++)
144
+ if (flag_out_on_off[i] != flag_out_on_off_prec[i]) // se un' uscita ha cambiato stato
145
+ {
146
+ flag_out_on_off_prec[i] = flag_out_on_off[i];
147
+ update_bufferTX_out(i); // aggiorna il bufferTX
148
+ TXX++;
149
+ bsave(PortaCOM, bufferTX, 4); // invia il bufferTX
150
+ // (comunicando attivazione/disattivazione dell'uscita i)
151
+ wait(10);
152
+ }
153
+
154
+ // controllo uscita pomp
155
+ if (flag_pomp_on_off != flag_pomp_on_off_prec) // se ha cambiato stato
156
+ {
157
+ flag_pomp_on_off_prec = flag_pomp_on_off;
158
+ update_bufferTX_pomp(); // aggiorna il bufferTX con i dati sul valore di pomp
159
+ TXX++;
160
+ bsave(PortaCOM, bufferTX, 2); // invia il bufferTX
161
+ wait(10);
162
+ }
163
+ if (flag_pomp_on_off) // se comunque pomp è accesa
164
+ {
165
+ update_bufferTX_pomp(); // aggiorna il bufferTX con il valore di pomp
166
+ TXX++;
167
+ bsave(PortaCOM, bufferTX, 2); // invia il bufferTX
168
+ wait(10);
169
+ }
170
+
171
+ // lettura ingressi
172
+ bufferTX[0] = READ_IN; // il primo byte del bufferTX viene impostato col comando READ_IN per comunicare che la // centrale vuole ricevere come risposta il valore di In e Potenz
173
+ TXX++;
174
+ bsave(PortaCOM, bufferTX, 1); // invia il bufferTX
175
+ wait(10);
176
+ }
177
+ }
178
+ }
179
+
180
+ // ogni 100 ms imposta la flag del tx della seriale a 1 (vedi start.c)
181
+ void tx485(void)
182
+ {
183
+ flag_tx485 = 1;
184
+ }
185
+
186
+ // funzione che aggiorna il bufferTX con i dati relativi allo stato delle uscite
187
+ // il parametro in ingresso è il numero dell'uscita che ha cambiato stato
188
+ void update_bufferTX_out(int x)
189
+ {
190
+ bufferTX[0] = OUT_ON_OFF; // imposta il primo byte del bufferTX con il comando OUT_ON_OFF
191
+ bufferTX[1] = x; // imposta il secondo byte del bufferTX con il numero dell'uscita
192
+ if (flag_out_on_off[x] == 0) // se l' uscita ha cambiato stato spengendosi
193
+ { // il terzo e quarto byte del bufferTX vengono impostati a 0 (off)
194
+ bufferTX[2] = 0;
195
+ bufferTX[3] = 0;
196
+ }
197
+ else // se ha cambiato stato accendendosi
198
+ {
199
+ if (x == 0 && flag_pwm_on_off) // se l' uscita è la 1 (x == 0) e se il pwm è attivo
200
+ { // il terzo e quarto byte del bufferTX vengono impostati con freq e pwm
201
+ bufferTX[2] = freq;
202
+ bufferTX[3] = pwm;
203
+ }
204
+ else // se l' uscita non è la 1 o se il pwm è disattivo
205
+ { // il terzo e quarto byte del bufferTX vengono impostati a 7 (on)
206
+ bufferTX[2] = 7;
207
+ bufferTX[3] = 7;
208
+ }
209
+ }
210
+ }
211
+
212
+ // funzione che aggiorna il bufferTX con il dati per settare l' uscita pomp;
213
+ void update_bufferTX_pomp(void)
214
+ {
215
+ bufferTX[0] = POMP_VEL; // imposta il primo byte del bufferTX con il comando POMP_VEL
216
+ bufferTX[1] = p; // imposta il secondo byte del bufferTX con il valore della variabile relativa alla velocità di pomp
217
+ // p dipende dal vaolore dello slider sl1 che si trova su una pagina grafica del progetto
218
+ // p = sl1->val;
219
+ }
220
+
221
+ // funzione che svuota il bufferRX
222
+ void clear_bufferRX(void)
223
+ {
224
+ for (int i = 0; i < dim_bufferRX; i++) // tutti i valori del bufferRX vengono messi a 0
225
+ bufferRX[i] = 0;
226
+ }
227
+
228
+Nello **start.c**:
229
+
230
+ init_serial_RS485(); // inizializza la seriale RS485
231
+ init_out(); // inizializza le uscite
232
+
233
+ exec_timer(tx485, 100, 0); // esegue ogni 100 ms tx485
234
+ exec_task(TaskCOM485, 0, 4); // esegue la TaskCOM485
235
+