Dopo un corposo aggiornamento di Windows 10 (tanto corposo che ho lasciato il calcolatore acceso di notte in attesa del termine) mi sono trovato il giorno successivo con il messaggio di Connettivita' Limitata sulla rete WiFi (il che tradotto vuol dire che il Pc si era collegato all'Access Point ma non era in grado di raggiungere Internet)
L'aggiornamento era stato via WiFi quindi la rete senza fili funzionava. Usando un Surface (hardware Microsoft) mi sono dovuto attrezzare con un dongle Usb-Ethernet per riguadagnare Internet e vedere se c'erano ulteriori aggiornamenti in attesa di installazione. Dopo un altro corposo aggiornamento la situazione e' rimasta identica...niente connessione via WiFi.
Questo problema era segnalato da altri utenti ma erano situazioni legate a upgrade da Windows 8 a Windows 10...quindi non il mio caso
La soluzione e' stata quella di ripristinare il driver della scheda di rete senza fili.
Certo che se Windows non funziona nemmeno su hardware Microsoft......
mercoledì 22 giugno 2016
martedì 21 giugno 2016
Webcam su Intel Edison
Il primo passo per utilizzare una webcam su Intel Edison e' quella di spostare il selettore SW2 dalla parte della porta USB standard. In questo modo si disattiva la porta microUsb OTG e si attiva la porta USB standard
Dal punto di vista dei moduli del kernel la mia Logitech C310 e' stata vista senza troppi problemi e montata in /dev/video0
Partendo dai repositori dai repository di AlexT (vedi qui) e' banale installare motion
In fase di compilazione pero' mjpeg-streamer si e' rifiutato per un errore piuttosto criptico su un plugin, penso dovuto al fatto che io ho installato v4l2 mentre mpjeg-streamer usa v4l.
Frugando su github ho trovato v4l2_mjpeg_streamer, una versione alleggerita di mjpeg_streamer basata su v4l2 che permette una trasmissione a 5 fotogrammi per secondo alla massima risoluzione della camera (al contrario di mjpeg_streamer la porta TCP e' la 8081)
Dal punto di vista dei moduli del kernel la mia Logitech C310 e' stata vista senza troppi problemi e montata in /dev/video0
Partendo dai repositori dai repository di AlexT (vedi qui) e' banale installare motion
motion in azione |
Piu' problematico invece far funzionare mjpeg-streamer. Scaricando via opkg da AlexT il pacchetto risulta andare in segmentation fault. Ho provato a ricompilare quindi dai sorgenti (l'ultima versione disponibile e' la r63) risolvendo le dipendenze e quindi installando anche v4l-utils.
In fase di compilazione pero' mjpeg-streamer si e' rifiutato per un errore piuttosto criptico su un plugin, penso dovuto al fatto che io ho installato v4l2 mentre mpjeg-streamer usa v4l.
Frugando su github ho trovato v4l2_mjpeg_streamer, una versione alleggerita di mjpeg_streamer basata su v4l2 che permette una trasmissione a 5 fotogrammi per secondo alla massima risoluzione della camera (al contrario di mjpeg_streamer la porta TCP e' la 8081)
venerdì 17 giugno 2016
Accuratezza di sensore ultrasonico SR-04
Per un lavoro di laboratorio e' necessario misurare la distanza di un campione senza toccarlo con un comparatore. Per questo motivo e' stata provato ad usare il sensore ultrasonico SR-04 come misuratore di distanza
La precisione richiesta era di 1 mm mentre le schede tecniche che si trovano su Internet parlano di un valore minimo di risoluzione di 3 mm..in ogni caso e' stata fatta una prova
Il bersaglio era costituito da una lamina di alluminio e il sensore e' stato collegato ad una Arduino Uno. Purtroppo non e' stato possibile mettere su un sistema che permetteva la perfetta ortogonalita' della sensore emittente con la superficie riflettente (questo e' un limite della presente misura)
Visto che il sensore non misura direttamente la distanza ma il tempo di volo di un impulso (la distanza si calcola a ritroso conoscendo la velocita' del suono nell'aria) e visto che la velocita' del suono nell'aria e' funzione della temperatura (e non della pressione) secondo un legge del tipo
(di seguito si usa il simbolo ms per indicare i microsecondi)
#include "Statistic.h"
#define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN 11 // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 50 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
Statistic myStats;
void setup() {
Serial.begin(115200);
myStats.clear();
}
void loop() {
delay(50);
myStats.add(sonar.ping());
if (myStats.count() == 500)
{
Serial.print(" Average: ");
Serial.print(myStats.average(), 2);
Serial.print(" Std deviation: ");
Serial.print(myStats.pop_stdev(), 2);
Serial.println();
}
}
La precisione richiesta era di 1 mm mentre le schede tecniche che si trovano su Internet parlano di un valore minimo di risoluzione di 3 mm..in ogni caso e' stata fatta una prova
Il bersaglio era costituito da una lamina di alluminio e il sensore e' stato collegato ad una Arduino Uno. Purtroppo non e' stato possibile mettere su un sistema che permetteva la perfetta ortogonalita' della sensore emittente con la superficie riflettente (questo e' un limite della presente misura)
Visto che il sensore non misura direttamente la distanza ma il tempo di volo di un impulso (la distanza si calcola a ritroso conoscendo la velocita' del suono nell'aria) e visto che la velocita' del suono nell'aria e' funzione della temperatura (e non della pressione) secondo un legge del tipo
velocita'_suono=331.4+0.62*temperatura (m/sec)
ho misurato il tempo di volo tramite la libreria NewPing spostando il bersaglio posto a distanza variabile intorno ai 20 cm, Per ogni posizione sono state effettuate 500 acquisizione che poi sono state mediate mediante la libreria Statistics di Arduino
(di seguito si usa il simbolo ms per indicare i microsecondi)
Lo sketch impiegato e' stato il seguente
------------------------------------------------
#include <NewPing.h>#include "Statistic.h"
#define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN 11 // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 50 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
Statistic myStats;
void setup() {
Serial.begin(115200);
myStats.clear();
}
void loop() {
delay(50);
myStats.add(sonar.ping());
if (myStats.count() == 500)
{
Serial.print(" Average: ");
Serial.print(myStats.average(), 2);
Serial.print(" Std deviation: ");
Serial.print(myStats.pop_stdev(), 2);
Serial.println();
}
}
------------------------------------------------
I dati, di una prova sicuramente parziale ma comunque indicativa della fattibilita', e' riportata nella figura successiva
Attenzione: si parla di tempi di andata e ritorno dell'impulso.
Molto indicativamente si ha che un centimetro di distanza corrisponde, nelle condizioni di misura, a circa 60 ms quindi se si vuole cerca di misurare una variazione di 1mm si deve riuscire a separare almeno 6 ms. Considerando che l'errore medio di deviazione standard e' di circa 3 ms usare l'SR-04 per misurare con la precisione del millimetro e' decisamente al limite delle proprie possibilita' (si comincia a ragionare se la risoluzione e' un decimo della grandezza che si vuole misurare)
secondo i dati teorici con temperatura di 20°C la velocita' del suono in aria e' di 0.0343 cm/ms (343 m/s) il tempo di volo e' di 6 ms per mm (andata e ritorno 2 mm) il che ritorna abbastanza bene con quanto misurato
mercoledì 15 giugno 2016
Amplificatore invertente AC con LM358
Ho fatto qualche esperimento con LM358 in passato (con risultati deludenti..per colpa mia).
Frugando su Internet ho trovato questo link dove viene indicato l'utilizzo di LM358 con un configurazione che non avevo mai usato
Il testo di riferimento citato nel testo del post non e' piu' disponibile ma sono riuscito a trovare una copia di Ops amps for Everyone a questo link
Con la configurazione sotto riportata il fattore di amplificazione e' data dalla tensione di ingresso per il rapporto tra Rf ed Rg piu' la tensione di alimentazione divisa per due (le due resistenze R di uguale entita' funzionano come un divisore di tensione)
Non avendo un microfono audio o un generato di segnale mi sono adattato a vedere l'amplificazione data da un piezoelettrico. In condizioni non amplificate il segnale massimo registrato e' stato di circa 5/6 unita' sull'ingresso analogico
passandolo per l'amplificatore si vede chiaramente che viene amplificato anche il rumore e l'intesita' del segnale e' passata a qualche centinaio di unita' (ho perso i dettagli delle resistenze che ho usato). Si vede anche che il segnale e' stato spostato al centro dell'asse delle Y (valore di circa 500 con una fondo scale di 1024 a bit 10)
Frugando su Internet ho trovato questo link dove viene indicato l'utilizzo di LM358 con un configurazione che non avevo mai usato
Il testo di riferimento citato nel testo del post non e' piu' disponibile ma sono riuscito a trovare una copia di Ops amps for Everyone a questo link
Con la configurazione sotto riportata il fattore di amplificazione e' data dalla tensione di ingresso per il rapporto tra Rf ed Rg piu' la tensione di alimentazione divisa per due (le due resistenze R di uguale entita' funzionano come un divisore di tensione)
Non avendo un microfono audio o un generato di segnale mi sono adattato a vedere l'amplificazione data da un piezoelettrico. In condizioni non amplificate il segnale massimo registrato e' stato di circa 5/6 unita' sull'ingresso analogico
passandolo per l'amplificatore si vede chiaramente che viene amplificato anche il rumore e l'intesita' del segnale e' passata a qualche centinaio di unita' (ho perso i dettagli delle resistenze che ho usato). Si vede anche che il segnale e' stato spostato al centro dell'asse delle Y (valore di circa 500 con una fondo scale di 1024 a bit 10)
martedì 14 giugno 2016
Crearsi una scatola per GPS Arduino
Quando un progetto di Arduino deve diventare operativo e' necessario costruirsi una scatola che alloggi l'elettronica e gli accessori. In questo post descrivo come ho creato la scatola per il mio GPS Arduino Ublox
Il primo passo fondamentale e' munirsi di distanziali (spacer) per bloccare la scheda elettrica alla scatola
Ne esistono sia in metallo (credo sia ottone) che in nylon. Io ho usato quelli in plastica. Il passo della vite e' da 3 per cui si puo' comprare anche minuteria metallica se la lunghezza delle viti del set non e' idonea
Come scatola ho preso una Gewiss GW 44 007 classificata come IP 55 (ovvero Protezione totale alla penetrazione di corpi solidi.Protezione contro la penetrazione di liquidi da gocce, vapori, spruzzi e getti d'acqua in qualsiasi direzione.)
L'utilizzo di questa scatola ha il vantaggio di avere dei tappi removibili che permettono il passaggio di un cavo USB di programmazione per poi richiudere il tutto senza necessariamente dovere rimuovere il coperchio e le sue viti
Il primo passo fondamentale e' munirsi di distanziali (spacer) per bloccare la scheda elettrica alla scatola
Ne esistono sia in metallo (credo sia ottone) che in nylon. Io ho usato quelli in plastica. Il passo della vite e' da 3 per cui si puo' comprare anche minuteria metallica se la lunghezza delle viti del set non e' idonea
Come scatola ho preso una Gewiss GW 44 007 classificata come IP 55 (ovvero Protezione totale alla penetrazione di corpi solidi.Protezione contro la penetrazione di liquidi da gocce, vapori, spruzzi e getti d'acqua in qualsiasi direzione.)
L'utilizzo di questa scatola ha il vantaggio di avere dei tappi removibili che permettono il passaggio di un cavo USB di programmazione per poi richiudere il tutto senza necessariamente dovere rimuovere il coperchio e le sue viti
Modalita' di programmazione |
Il progetto prevede di montare sul coperchio l'antenna GPS (all'interno) ed il pannello solare (all'esterno)
Montati i distanziali sull'antenna si devono fare i fori sul coperchio...ma come farli precisi?? Un piccolo trucco. Si macchia il distanziale con un pennarello, essendo di nylon l'inchiostro non penetra e basta appoggiare il tutto sul coperchio per ottenere l'impronta di dove forare.La punta del trapano da usare e' quella da 3
Il risultato finale e' questo
Per montare il pannello solare si deve praticare un foro per passare i fili all'interno della scatola e dei distanziali per sostenere il pannello. Visto che il pannello solare era privo di prefori ho usato dei gommini di plastica fermati da una vite a ferro (fare prima un preforo prima di avvitare la vite perche' la plastica e' molto scivolosa e ci vuole un foro guida)
Per fissare il pannello al coperchio e' sufficiente usare una abbondante dose di silicone
Si passa all'interno della scatola. Su Arduino Uno sono stati montati gli spacer (in questo caso hanno trovato posto solo tre spacer su quattro fori perche' il dado di serraggio dello spacer e' troppo grande...non un gran male perche' comunque sul fondo della scatola ci sono dei bordi rialzati che si possono utilizzare come appoggio)
Per trovare il punto giusto di realizzazione dei fori si usa lo stesso metodo precedente
La batteria invece e' stata bloccata con del velcro.
A questo punto si devono mettere insieme i pezzi (scatola e coperchio). Qui l'unica attenzione e' quella di allungare tutti i cavi in modo da rendere agevole. E' anche comodo scegliere un lato di apertura della scatola e di marcarla sulla scatola in modo da aprire sempre dallo stesso verso (questo per non aprire per sbaglio un un lato per cui i cavi vanno in tensione)
lunedì 13 giugno 2016
LCD1602 su PIC DevBoard
Codice, ripreso da un produttore cinese, su come usare LCD1602 con PIC. Compilatore MapLab IDE
main.c
---------------------------------------------
#include <pic.h>
#include "LCD1602.h"
//---------------------------------------
unsigned char str0[]={"Luca "};
unsigned char str1[]={"Innocenti "};
unsigned char str2[]={"debiaonoldcomput"};
unsigned char str3[]={"ers.blogspot.com"};
//---------------------------------------
void main(void)
{
LCD1602_GPIO_Init();
LCD1602_init();
while(1)
{
DisplayListChar(0,0,str0);
DisplayListChar(0,1,str1);
Delay1602_MS(500);
DisplayListChar(0,0,str2);
DisplayListChar(0,1,str3);
Delay1602_MS(500);
}
}
---------------------------------------------
LCD1602.H
---------------------------------------------
#ifndef __LCD1602_H
#define __LCD1602_H
#define E RA3
#define RW RA2
#define RS RA5
#define busy RD7
#define busy_init TRISD7
#define Lcd_Date PORTD
void Delay1602_US(unsigned int t);
void Delay1602_MS(unsigned int t);
void LCD1602_BusyTest(void);
void LCD1602_Write_Instruction(unsigned char combuf);
void LCD1602_Write_data_busy(unsigned char databuf);
void LCD1602_init(void);
void DisplayOneChar(unsigned char X,unsigned char Y,unsigned char DData);
void DisplayListChar(unsigned char X,unsigned char Y,unsigned char *DData);
void LCD1602_GPIO_Init(void);
#endif
---------------------------------------------
1602.c
---------------------------------------------
#include <pic.h>
#include "LCD1602.h"
__CONFIG(HS&WDTDIS&LVPDIS);
void Delay1602_US(unsigned int t)
{
unsigned int k;
for(k=0;k<t;k++);
}
void Delay1602_MS(unsigned int t)
{
while(t--)
Delay1602_US(200);
}
void LCD1602_BusyTest(void)
{
busy_init=1;
RS=0;
RW=1;
E=1;
asm("NOP");
asm("NOP");
while(busy==1);
E=0;
busy_init=0;
}
void LCD1602_Write_Instruction(unsigned char combuf)
{
LCD1602_BusyTest();
RS=0;
RW=0;
E=0;
asm("NOP");
Lcd_Date=combuf;
asm("NOP");
asm("NOP");
E=1;
asm("NOP");
E=0;
}
void LCD1602_Write_data_busy(unsigned char databuf)
{
LCD1602_BusyTest();
RS=1;
RW=0;
E=0;
asm("NOP");
Lcd_Date=databuf;
asm("NOP");
asm("NOP");
E=1;
asm("NOP");
E=0;
}
void LCD1602_init(void)
{
Delay1602_US(1500);
LCD1602_Write_Instruction(0x38);
Delay1602_US(500);
LCD1602_Write_Instruction(0x38);
Delay1602_US(500);
LCD1602_Write_Instruction(0x38);
LCD1602_Write_Instruction(0x38);
LCD1602_Write_Instruction(0x08);
LCD1602_Write_Instruction(0x01);
LCD1602_Write_Instruction(0x06);
LCD1602_Write_Instruction(0x0C);
}
void DisplayOneChar(unsigned char X,unsigned char Y,unsigned char DData)
{
Y&=1;
X&=15;
if(Y)X|=0x40;
X|=0x80;
LCD1602_Write_Instruction(X);
LCD1602_Write_data_busy(DData);
}
void DisplayListChar(unsigned char X,unsigned char Y,unsigned char *DData)
{
unsigned char ListLength=0;
Y&=0x01;
X&=0x0f;
while(X<16)
{
DisplayOneChar(X,Y,DData[ListLength]);
ListLength++;
X++;
}
}
void LCD1602_GPIO_Init(void)
{
ADCON1=0X07;
TRISA=0B11010011;
TRISD=0B00000000;
PORTA=0B00000000;
PORTD=0B00000000;
}
---------------------------------------------
Schema elettrico |
main.c
---------------------------------------------
#include <pic.h>
#include "LCD1602.h"
//---------------------------------------
unsigned char str0[]={"Luca "};
unsigned char str1[]={"Innocenti "};
unsigned char str2[]={"debiaonoldcomput"};
unsigned char str3[]={"ers.blogspot.com"};
//---------------------------------------
void main(void)
{
LCD1602_GPIO_Init();
LCD1602_init();
while(1)
{
DisplayListChar(0,0,str0);
DisplayListChar(0,1,str1);
Delay1602_MS(500);
DisplayListChar(0,0,str2);
DisplayListChar(0,1,str3);
Delay1602_MS(500);
}
}
---------------------------------------------
LCD1602.H
---------------------------------------------
#ifndef __LCD1602_H
#define __LCD1602_H
#define E RA3
#define RW RA2
#define RS RA5
#define busy RD7
#define busy_init TRISD7
#define Lcd_Date PORTD
void Delay1602_US(unsigned int t);
void Delay1602_MS(unsigned int t);
void LCD1602_BusyTest(void);
void LCD1602_Write_Instruction(unsigned char combuf);
void LCD1602_Write_data_busy(unsigned char databuf);
void LCD1602_init(void);
void DisplayOneChar(unsigned char X,unsigned char Y,unsigned char DData);
void DisplayListChar(unsigned char X,unsigned char Y,unsigned char *DData);
void LCD1602_GPIO_Init(void);
#endif
---------------------------------------------
1602.c
---------------------------------------------
#include <pic.h>
#include "LCD1602.h"
__CONFIG(HS&WDTDIS&LVPDIS);
void Delay1602_US(unsigned int t)
{
unsigned int k;
for(k=0;k<t;k++);
}
void Delay1602_MS(unsigned int t)
{
while(t--)
Delay1602_US(200);
}
void LCD1602_BusyTest(void)
{
busy_init=1;
RS=0;
RW=1;
E=1;
asm("NOP");
asm("NOP");
while(busy==1);
E=0;
busy_init=0;
}
void LCD1602_Write_Instruction(unsigned char combuf)
{
LCD1602_BusyTest();
RS=0;
RW=0;
E=0;
asm("NOP");
Lcd_Date=combuf;
asm("NOP");
asm("NOP");
E=1;
asm("NOP");
E=0;
}
void LCD1602_Write_data_busy(unsigned char databuf)
{
LCD1602_BusyTest();
RS=1;
RW=0;
E=0;
asm("NOP");
Lcd_Date=databuf;
asm("NOP");
asm("NOP");
E=1;
asm("NOP");
E=0;
}
void LCD1602_init(void)
{
Delay1602_US(1500);
LCD1602_Write_Instruction(0x38);
Delay1602_US(500);
LCD1602_Write_Instruction(0x38);
Delay1602_US(500);
LCD1602_Write_Instruction(0x38);
LCD1602_Write_Instruction(0x38);
LCD1602_Write_Instruction(0x08);
LCD1602_Write_Instruction(0x01);
LCD1602_Write_Instruction(0x06);
LCD1602_Write_Instruction(0x0C);
}
void DisplayOneChar(unsigned char X,unsigned char Y,unsigned char DData)
{
Y&=1;
X&=15;
if(Y)X|=0x40;
X|=0x80;
LCD1602_Write_Instruction(X);
LCD1602_Write_data_busy(DData);
}
void DisplayListChar(unsigned char X,unsigned char Y,unsigned char *DData)
{
unsigned char ListLength=0;
Y&=0x01;
X&=0x0f;
while(X<16)
{
DisplayOneChar(X,Y,DData[ListLength]);
ListLength++;
X++;
}
}
void LCD1602_GPIO_Init(void)
{
ADCON1=0X07;
TRISA=0B11010011;
TRISD=0B00000000;
PORTA=0B00000000;
PORTD=0B00000000;
}
---------------------------------------------
Emulatori 6502 su Arduino
Andando a giro su Internet ho scoperto che esiste la possibilta' di emulare il glorioso processore MOS 6502 (e la sua variante MOS 6510) su Arduino.
Esistono diversi progetti come quello per il C64, per il VIC 20 ed il KIM-1.
Per emulare il C64 e' necessario utilizzare una Arduino Due a causa della mancanza di memoria della scheda Uno
Una volta caricato il programma (da qui) ci si deve collegare via seriale ma non usando il terminale seriale di Arduino IDE (Minicom e Hyperterminal funzionano, configurazione 9600 8N1). Ci si trova davanti all'interprete BASIC
a parte lo spazio di memoria libera veramente esigua il sistema funziona
Un po' (un bel po') piu' impegnativo e' usare l'emulatore del KIM-1 (funzionante anche su Arduino Uno e reperibile a questo indirizzo) perche' di fatto il sistema si programma direttamente in Linguaggio Macchina (non e' un errore, non si programma in Assembler, si inputa il codice direttamente in LM)
Come nel caso precedente si deve usare un terminale seriale esterno alla IDE di Arduino
La cosa piu' divertente e' pero' dare un'occhiata al file cpu.c dove e' contenuta la divisione della memoria con eventuali programmi caricati come ROM, la traduzione delle istruzioni in Assembler 6502 comprese quelle non documentate e la gestione degli interrupt
Esistono diversi progetti come quello per il C64, per il VIC 20 ed il KIM-1.
Per emulare il C64 e' necessario utilizzare una Arduino Due a causa della mancanza di memoria della scheda Uno
Una volta caricato il programma (da qui) ci si deve collegare via seriale ma non usando il terminale seriale di Arduino IDE (Minicom e Hyperterminal funzionano, configurazione 9600 8N1). Ci si trova davanti all'interprete BASIC
a parte lo spazio di memoria libera veramente esigua il sistema funziona
Un po' (un bel po') piu' impegnativo e' usare l'emulatore del KIM-1 (funzionante anche su Arduino Uno e reperibile a questo indirizzo) perche' di fatto il sistema si programma direttamente in Linguaggio Macchina (non e' un errore, non si programma in Assembler, si inputa il codice direttamente in LM)
Come nel caso precedente si deve usare un terminale seriale esterno alla IDE di Arduino
La cosa piu' divertente e' pero' dare un'occhiata al file cpu.c dove e' contenuta la divisione della memoria con eventuali programmi caricati come ROM, la traduzione delle istruzioni in Assembler 6502 comprese quelle non documentate e la gestione degli interrupt
Iscriviti a:
Post (Atom)
Debugger integrato ESP32S3
Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede nell'ID USB della porta Jtag. Nel modulo...
-
In questo post viene indicato come creare uno scatterplot dinamico basato da dati ripresi da un file csv (nel dettaglio il file csv e' c...
-
La scheda ESP32-2432S028R monta un Esp Dev Module con uno schermo TFT a driver ILI9341 di 320x240 pixels 16 bit colore.Il sito di riferiment...
-
Questo post e' a seguito di quanto gia' visto nella precedente prova Lo scopo e' sempre il solito: creare un sistema che permet...