Skip to content

Commit 6fa5145

Browse files
committed
final updates
1 parent f43a886 commit 6fa5145

File tree

2 files changed

+92
-33
lines changed

2 files changed

+92
-33
lines changed

README.md

+91-32
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
![GitHub Logo](circuit.jpg)
66

7-
All'avvio vengono inizializzati i registri per la comunicazione seriale (UART), l'uso dei timer (TIMER1), i pin digitali, l'LCD (usata [libreria esterna](http://winavr.scienceprog.com/example-avr-projects/avr-gcc-4-bit-and-8-bit-lcd-library.html)), l'interfaccia ADC (definita appositamente in [adc.c](src/adc.c)) e gli external interrupt (INT0, INT1).
7+
All'avvio vengono inizializzati i registri per la comunicazione seriale (UART), i pin digitali, l'LCD (usata [libreria esterna](http://winavr.scienceprog.com/example-avr-projects/avr-gcc-4-bit-and-8-bit-lcd-library.html)), l'interfaccia ADC (definita appositamente in [adc.c](src/adc.c)) e gli external interrupt (INT0, INT1).
88

99
```c
10-
EIMSK = (1<<INT1)|(1<<INT0); //Turn ON INT0 and INT1
10+
EIMSK = (1<<INT1)|(1<<INT0); //turn ON INT0 and INT1
1111
EICRA = (1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00);
1212
```
1313

@@ -43,50 +43,74 @@ ISR(INT0_vect){ //external interrupt service routine
4343
reset = 1;
4444
waitingForOutput = 0;
4545
}
46+
else if(!waitingForOutput && !EEPROM_params_ready && DigIO_getValue(buttonLeft) == HIGH){
47+
EEPROM_params_ready = 1;
48+
}
4649
}
4750

4851
ISR(INT1_vect){ //external interrupt service routine
4952
if(waitingForOutput && DigIO_getValue(buttonRight) == HIGH){
5053
reset = 0;
5154
waitingForOutput = 0;
5255
}
56+
else if(!waitingForOutput && !EEPROM_params_ready && DigIO_getValue(buttonRight) == HIGH){
57+
EEPROM_params_ready = 1;
58+
}
5359
}
5460
```
5561
56-
Nel primo caso (`reset = 1`) l'MCU interagisce con l'utente tramite seriale per ottenere i nuovi parametri di configurazione e salvarli in EEPROM, ognuno in blocchi da 16 byte come di seguito riportato. Sono state scritte funzioni apposite per lettura/scrittura da/su EEPROM definite in [eepromParams.c](src/eepromParams.c)
62+
Nel primo caso (`reset = 1`) l'MCU installa gli handler per i pacchetti binari e attende dall'utente l'arrivo dei ConfigPacket contenenti i nuovi parametri di configurazione (continua a flushare l'input buffer), salva i singoli valori in EEPROM, ognuno in blocchi da 16 byte come di seguito riportato. Sono state scritte funzioni apposite per lettura/scrittura da/su EEPROM definite in [eepromParams.c](src/eepromParams.c)
63+
64+
**N.B**: dopo aver premuto il pushbutton associato a INT0 [sendParams.c](host/sendParams.c) è il programma da eseguire su host per scegliere e inviare i nuovi settaggi. Si veda più avanti il paragrafo sulla comunicazione seriale.
5765
58-
![GitHub Logo](EBFNflora_buffer.PNG)
66+
![GitHub Logo](EBFNflora_buffer.jpeg)
5967
6068
* `uint16_t timer`: intervallo in ms tra due successivi controlli dei sensori
6169
* `uint16_t minLight`
6270
* `uint16_t maxLight`
6371
* `uint16_t minTemp`
6472
* `uint16_t maxTemp`
65-
* `uint16_t maxPoll`: massimo valore della qualità dell'aria tollerato, consigliabile 150-170
66-
* `float R1`: resistenza per il calcolo della temperatura, nel circuito 10000
73+
* `float R1`: resistenza in Ω impiegata per il calcolo della temperatura, nel circuito 10000
6774
* `float C1, C2, C3`: costanti, vedere [Termistore](#Termistore)
75+
* `uint16_t maxPoll`: massimo valore della qualità dell'aria tollerato, consigliabile 150-170
76+
77+
**N.B**: [eeprom_test.c](eeprom_test.c) è un programma di debugging scritto per leggere i valori correnti in EEPROM.
6878
69-
**N.B**: il programma [eeprom_test.c](eeprom_test.c) è stato scritto per leggere i valori correnti in EEPROM.
79+
Una volta che i parametri sono stati modificati, l'utente può premere un qualunque pushbutton per uscire dal loop (il flag `EEPROM_params_ready` è settato a 1) e disinstallare gli handler dei pacchetti.
7080
71-
Nel secondo caso (`reset = 0`) i valori già presenti in EEPROM - quelli dell'ultimo setup - sono salvati subito nelle variabili globali.
81+
Nel secondo caso (`reset = 0`) l'MCU va subito a salvare i valori già presenti in EEPROM nelle variabili globali, cioé quelli dell'ultimo setup.
7282
7383
```c
7484
timer = get_EEPROM_timer();
7585
minLight = get_EEPROM_minLight();
7686
maxLight = get_EEPROM_maxLight();
7787
minTemp = get_EEPROM_minTemp();
7888
maxTemp = get_EEPROM_maxTemp();
79-
maxPoll = get_EEPROM_maxPoll();
8089
R1 = get_EEPROM_r1();
8190
C1 = get_EEPROM_c1();
8291
C2 = get_EEPROM_c2();
8392
C3 = get_EEPROM_c3();
93+
maxPoll = get_EEPROM_maxPoll();
94+
```
95+
96+
A questo punto:
97+
98+
* vengono disattivati i bit dei registri per gli external interrupt perché non saranno più utilizzati
99+
* viene inizializzato il timer basato sul TIMER1
100+
101+
```c
102+
//disable interrupts globally to turn OFF INT0 and INT1
103+
cli();
104+
EIMSK = 0x00;
105+
EICRA = 0x00;
106+
Timers_init(); //initialize timer
107+
sei(); //enable interrupts globally
84108

85109
struct Timer* timerSensors = Timer_create("timer_0", timer, timerFn, NULL);
86110
Timer_start(timerSensors);
87111
```
88112
89-
Il valore in `timer` è usato per richiamare ogni "timer" ms la funzione `timerFn()` che si occupa di effettuare il sensing dell'ambiente.
113+
Il valore memorizzato in `timer` è usato per richiamare ogni "timer" ms la funzione `timerFn()` che si occupa di effettuare il sensing dell'ambiente.
90114
91115
```c
92116
void timerFn(void* args){
@@ -115,36 +139,72 @@ Il microcontrollore entra infine in un loop vuoto ed eseguirà la funzione `time
115139

116140
## Comunicazione seriale
117141

118-
Il baudrate selezionato è 115200. Il formato dei frame adottato in [uart.c](src/uart.c) prevede 1 start bit, 8 bits data (`UCSR0C = _BV(UCSZ01) | _BV(UCSZ00)`), nessun bit di parità (nel registro UCSR0C i bit UPM01=0 e UPM00=0), 1 stop bit (nel registro UCSR0C il bit USBS0=0). Il programma [sendParams.c](sendParams.c) scritto per comunicare via terminale e configurare così i parametri in EEPROM utilizza la stessa configurazione per i pacchetti.
142+
### Lato Microcontrollore
119143

120-
```c
121-
speed_t baud = B115200; /* baud rate */
144+
Nei paragrafi precedenti si è visto che si instaura una comunicazione seriale binaria a pacchetti solo per trasmettere i parametri di misurazione. Esistono 4 tipi di ConfigPacket:
122145

123-
struct termios settings;
124-
tcgetattr(fd, &settings);
146+
```c
147+
typedef struct TimerConfigPacket{
148+
PacketHeader header;
149+
uint32_t duration;
150+
} TimerConfigPacket;
151+
152+
typedef struct LightConfigPacket{
153+
PacketHeader header;
154+
uint16_t minLight;
155+
uint16_t maxLight;
156+
} LightConfigPacket;
157+
158+
typedef struct TemperatureConfigPacket{
159+
PacketHeader header;
160+
uint16_t minTemp;
161+
uint16_t maxTemp;
162+
float r1;
163+
float c1;
164+
float c2;
165+
float c3;
166+
} TemperatureConfigPacket;
167+
168+
typedef struct PollutionConfigPacket{
169+
PacketHeader header;
170+
uint16_t maxPoll;
171+
} PollutionConfigPacket;
172+
```
125173

126-
cfsetospeed(&settings, baud); /* baud rate */
127-
settings.c_cflag &= ~PARENB; /* no parity */
128-
settings.c_cflag &= ~CSTOPB; /* 1 stop bit */
129-
settings.c_cflag &= ~CSIZE;
130-
settings.c_cflag |= CS8 | CLOCAL; /* 8 bits */
131-
settings.c_lflag = ICANON; /* canonical mode */
132-
settings.c_oflag &= ~OPOST; /* raw output */
174+
Ognuno dei precedenti è dotato di una funzione "onReceive" che estrae il payload, carica in EEPROM i nuovi parametri e li mostra sull'LCD come feedback per l'utente. A titolo di esempio ecco la funzione per il PollutionConfigPacket:
133175

134-
tcsetattr(fd, TCSANOW, &settings); /* apply the settings */
135-
tcflush(fd, TCOFLUSH);
176+
```c
177+
PacketStatus PollutionConfigPacket_onReceive(PacketHeader* header, void* args __attribute__((unused))){
178+
PollutionConfigPacket* p = (PollutionConfigPacket*) header;
179+
int maxPoll = p->maxPoll;
180+
set_EEPROM_maxPoll(maxPoll);
181+
char buffer[8];
182+
sprintf(buffer, "%d", maxPoll);
183+
LCDclr();
184+
printOnLCD(buffer);
185+
return Success;
186+
}
136187
```
137-
Il programma riconosce la fine di un messaggio grazie a un carattere speciale (`'\0' oppure '\n'`), legge da `stdin` la stringa digitata dall'utente e la invia al microcontrollore dopo aver aggiunto il terminatore `\0`. Il ciclo è ripetuto 7 volte, cioé per ogni parametro configurabile in EEPROM.
138188
139-
Dall'altro lato l'MCU salva la stringa ricevuta nella EEPROM, e.g. la variabile timer:
189+
### Lato Host
190+
191+
Il programma [sendParams.c](host/sendParams.c) avvia di fatto una procedura guidata per l'inserimento dei parametri. Chiede un parametro alla volta, lo legge da stdin, lo converte da char* al tipo corretto, prepara il singolo pacchetto e lo invia. Di seguito un esempio con il LightConfigPacket.
140192
141193
```c
142-
printString("timer in ms?\n");
143-
readString(rx_message, BUFFER_SIZE);
144-
set_EEPROM_timer(rx_message);
194+
printf("Insert min light: ");
195+
read_from_stdin();
196+
uint16_t minLight = atoi(inputString);
197+
198+
printf("Insert max light: ");
199+
read_from_stdin();
200+
uint16_t maxLight = atoi(inputString);
201+
202+
LightConfigPacket p1 = { {LIGHT_CONFIG_PACKET_TYPE, LIGHT_CONFIG_PACKET_SIZE, 0}, minLight, maxLight };
203+
PacketHandler_sendPacket(&packet_handler, (PacketHeader*) &p1);
204+
flushOutputBuffer(fd);
145205
```
146206

147-
**N.B**: `void readString(char* dest, int size)` è una funzione definita in [main.c](main.c) per salvare in un buffer i caratteri ricevuti.
207+
L'host non ha funzioni di ricezione "onReceive" per i pacchetti perché si occupa solo di inviare valori. Naturalmente - per come è stato progettato il [main.c](main.c) - saranno ignorati i pacchetti inviati senza aver premuto il pushbutton associato a INT0 oppure dopo che gli external interrupt sono stati disabilitati.
148208

149209
## Sensori
150210

@@ -188,7 +248,7 @@ void controlPoll(void){
188248
char msg[BUFFER_SIZE];
189249
190250
if(air_value>maxPoll){
191-
sprintf(msg, "Polluted air %d", air_value);
251+
sprintf(msg, "Polluted air");
192252
printOnLCD(msg);
193253
sprintf(msg, "Air: %d", air_value);
194254
LCDGotoXY(0,1);
@@ -243,4 +303,3 @@ La variabile Tc indica la temperatura attuale.
243303
* `Tc = T - 273.15` lo converte in °C.
244304
245305
Se la temperatura attuale non è nell'intervallo `[minTemp,maxTemp]` viene invocata la funzione `error_blink()` e viene stampato un messaggio di errore.
246-

main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -439,11 +439,11 @@ int main(void){
439439
maxLight = get_EEPROM_maxLight();
440440
minTemp = get_EEPROM_minTemp();
441441
maxTemp = get_EEPROM_maxTemp();
442-
maxPoll = get_EEPROM_maxPoll();
443442
R1 = get_EEPROM_r1();
444443
C1 = get_EEPROM_c1();
445444
C2 = get_EEPROM_c2();
446445
C3 = get_EEPROM_c3();
446+
maxPoll = get_EEPROM_maxPoll();
447447

448448
//disable interrupts globally to turn OFF INT0 and INT1
449449
cli();

0 commit comments

Comments
 (0)