Arduo Memory Reminder Medicine

:sweat_smile:
Grazie tuxduino della gentile risposta. Un pò più chiaro ora il concetto sull'uso delle librerie, ma rimane il fatto che bisogna conoscerle e per conoscerle bisogna usarle ed in primis, sapere dove cercarle e come.
A riguardo sai se esiste un elenco dettagliato di tutte o quasi, a parte quelle licenziate da arduino?

Ora provo a scaricare la 1.0.2, la 0023 dovrei già averla scaricata e verifico la compilazione.

Ciao.

A riguardo sai se esiste un elenco dettagliato di tutte o quasi, a parte quelle licenziate da arduino?

Più che di librerie "licenziate" direi incluse insieme all'IDE.

Per quanto riguarda un elenco completo... Proprio qui sul sito di arduino trovi un bel po' di materiale scritto dagli utenti, organizzato per tipo di funzionalità, nella sezione Playground (ma forse lo sapevi già...).
Per il resto non credo esista un elenco aggiornato e affidabile, per il semplice motivo che ognuno può scrivere una classe(ttina) e pubblicarla.
Di solito i negozi online più rinomati pubblicano una libreria a corredo delle schede o degli shield che vendono.
Ad esempio ho appena acquistato un motor shield della adafruit: sul sito è ben pubblicizzata anche la relativa libreria, veramente facile da usare anche senza studiarla.
Altrimenti faccio una normale ricerca su google: arduino + la parola chiave della funzionalità che cerco porta quasi sempre a dei buoni risultati.

:slight_smile:

:stuck_out_tongue:
Ho portato avanti il codice iniziale R05d, inserendo i dati in eprom e creando un array di default che solo se si tiene premuto il tasto down all'accensione, il device carica i dati di default in ram, e sovrascrive la eprom.

Giusto per non restare fermo.

Ho preferito non toccare nulla del tuo, anche perchè il confronto parallelo, porta ad un upgrade più completo.
Mi spiego: se ci concentriamo tutti e due sullo stesso argomento, c'è il rischio di non venirne a capo.
Nel momento in cui uno dei due trova una soluzione, la si può condividere ed utilizzare per perfezionare il codice.
Che ne pensi ?

Io mi sto organizzando per recuperare l'RTC, perchè non vedo soluzioni, a parte il ponticello HD e la modifica SW per ovviare al reset collegando il device al PC.

Il discorso LCD e tastiera è al momento trascurabile. Quando avremo bisogno di pin ci penseremo.

Ciao, ti rispondo in ordine sparso...

L'uso di un RTC secondo me è imprescindibile per rendere veramente completo il tuo progetto :slight_smile:

Interessante l'idea del reset degli allarmi tenendo premuto il tasto all'avvio :slight_smile:
Appena ho un attimo do un'occhiata al tuo nuovo codice.

Nel frattempo ho compilato il mio sotto 0023: non compila per l'assenza della macro F(), utilizzata per spostare facilmente le stringhe in PROGMEM, ma assente nella 0023. Metto una #define per risolvere la cosa.

Credo anch'io che sia meglio portare avanti i due codici in parallelo, almeno per ora :slight_smile:

Infine, per quanto riguarda il consumo di pin... Nel caso serva, basta usare un lcd seriale: usa soltanto 1 pin per la ricezione dei caratteri; dal punto di vista software invece della LiquidCrystal si usa la SoftareSerial e si inviano semplicemente i caratteri da visualizzare (e giusto un paio di byte particolari per pulire il display e impostare la posizione del cursore...)
Per la tastiera non saprei... ma come hai detto tu non è prioritario per ora.

:wink:
Ho postato sul FABLAB la release R05F con gli aggiornamenti dell'array dei parametri di default ed il backup su eprom.

Nella prossima release "R05G" verranno aggiornate tutte le descrizioni delle funzioni, per rendere più comprensibile il codice.

Ricordo che il funzionamento esatto del device con tutte le funzioni ad oggi disponibili, sarà aggiornato non appena tuxduino avrà disponibile una release completa.

A giorni posterò il funzionamento completo fino alla release R05F/R05G con tanto di esempi.

Un saluto a tutti.
Giuseppe G.

Ciao Giuseppe,
leggendo la funzione verirow() c'è una cosa che non capisco: perché cambi la modalità dei pin da INPUT a OUTPUT e viceversa ?
Grazie!

(edit: forse è per mettere il pin in alta impedenza e impedire così l'accensione di entrambi i led ?)

Sempre a proposito della verirow(), ho ricavato la "tabella della verità", cioè la configurazione e i valori di uscita delle linee in base al numero del paziente e al numero della medicina.

Codificando queste informazioni sottoforma di array si potrebbe riscrivere la funzione in modo molto più conciso.
Si potrebbe arrivare ad una funzione utilizzabile così:

verirow(patientNum, medicineNum);

patient 1

mednum    line1 line2 line3    a0    a1    a2    a3    a4
   1       O,1   I     I       I     O,0   I     I     I
   2       I     O,1   I       I     O,0   I     I     I
   3       I     I     O,1     I     O,0   I     I     I
   4       I     I     I       O,1   O,0   I     I     I
   5       O,1   I     I       I     I     O,0   I     I
   6       I     O,1   I       I     I     O,0   I     I
   7       I     I     O,1     I     I     O,0   I     I
   8       I     I     I       O,1   I     O,0   I     I
   9       O,1   I     I       I     I     I     O,0   I
  10       I     O,1   I       I     I     I     O,0   I
  11       I     I     O,1     I     I     I     O,0   I
  12       I     I     I       O,1   I     I     O,0   I
  13       O,1   I     I       I     I     I     I     O,0
  14       I     O,1   I       I     I     I     I     O,0
  15       I     I     O,1     I     I     I     I     O,0
  16       I     I     I       O,1   I     I     I     O,0

patient 2

mednum    line1 line2 line3    a0    a1    a2    a3    a4
   1       O,0   I     I       I     O,1   I     I     I
   2       I     O,0   I       I     O,1   I     I     I
   3       I     I     O,0     I     O,1   I     I     I
   4       I     I     I       O,0   O,1   I     I     I
   5       O,0   I     I       I     I     O,1   I     I
   6       I     O,0   I       I     I     O,1   I     I
   7       I     I     O,0     I     I     O,1   I     I
   8       I     I     I       O,0   I     O,1   I     I
   9       O,0   I     I       I     I     I     O,1   I
  10       I     O,0   I       I     I     I     O,1   I
  11       I     I     O,0     I     I     I     O,1   I
  12       I     I     I       O,0   I     I     O,1   I
  13       O,0   I     I       I     I     I     I     O,1
  14       I     O,0   I       I     I     I     I     O,1
  15       I     I     O,0     I     I     I     I     O,1
  16       I     I     I       O,0   I     I     I     O,1

Dunque... ho studiato un po' lo schema elettrico. Mi sembra che la verirow() si possa semplificare...
Ho buttato giù una funzione generica per pilotare la matrice di led. Ecco il codice:

const byte NUM_ROWS = 4;
const byte NUM_COLS = 4;

byte rowPins[NUM_ROWS] = { A1, A2, A3, A4 };
byte colPins[NUM_ROWS] = {  8,  9, 10, A0 };

// tutti i pin che pilotano la matrice sono di OUTPUT
// quesat routine va chiamata in setup()
void pinSetup() {
    byte i;
    
    for (i = 0; i < NUM_COLS; i++) {
        pinMode(colPins[i], OUTPUT);
    }
    
    for (i = 0; i < NUM_ROWS; i++) {
        pinMode(rowPins[i], OUTPUT);
    }
}


// spegne tutti i led
void allOff() {
    byte i;
    
    for (i = 0; i < NUM_COLS; i++) {
        digitalWrite(colPins[i], LOW);
    }
    
    for (i = 0; i < NUM_ROWS; i++) {
        digitalWrite(rowPins[i], LOW);
    }
}


// accende tutti i led di un colore o dell'altro
void allOn(byte highOrLow) {
    byte i;
    
    for (i = 0; i < NUM_COLS; i++) {
        digitalWrite(colPins[i], highOrLow);
    }
    
    for (i = 0; i < NUM_ROWS; i++) {
        digitalWrite(rowPins[i], !highOrLow);
    }
}


// cellNumber: 0..ROW*COLS
// value: HIGH or LOW
void writeCell(byte cellNum, byte value) {
    byte row;
    byte col;
    
    row = cellNum / NUM_COLS;
    col = cellNum % NUM_COLS;
    
    allOff();

    digitalWrite(colPins[col], value);
    digitalWrite(rowPins[row], !value);
}

Il codice compila, ma ovviamente non l'ho provato sull'hardware... In allegato trovi questo codice unito a setup() e loop() a formare uno sketch di prova che dovrebbe semplicemente illuminare uno ad uno i led in sequenza, prima di un colore, poi dell'altro.

Penso che questo codice si possa già integrare nel tuo, sostituendo il corpo della verirow() con una roba tipo questa (tieni conto che nel mio codice l'indice della cella va da 0 a 15, non da 1 a 16):

if numero medicina == 0
allOff()
return

if numero medicina <= 16
writeCell(numero medicina - 1, 0)
else
writeCell(numero medicina - 16 - 1, 1);
endif

Ciao!

AMR_LedMatrixTest.ino (1.47 KB)

Ciao Giuseppe,
leggendo la funzione verirow() c'è una cosa che non capisco: perché cambi la modalità dei pin da INPUT a OUTPUT e viceversa ?
Grazie!

(edit: forse è per mettere il pin in alta impedenza e impedire così l'accensione di entrambi i led ?)

Ciao tuxduino, :wink:
è proprio così, se tengo a +5V o a 0V, quando la inea dei primi 4 led ad esempio viene portata a +5V, questa fà si che si accendano tutti e 4.

Buona l'idea quella della matrice, che potrebbe diventare un libreria per gestire fino a 162 led indipendenti con la UNO (dove ci saranno 9 linee per 9 righe, moltiplicato 2 "per la polarizzazione"), una buona soluzione per un gioco di luci!!! (visto che siamo sotto natale!)

Se puoi, verifica l'hardware, ma io non ho trovato altre soluzioni al di fuori che questa.

=(
Non saprei neanche da dove cominciare però per creare una nuova libreria, ci sono consigli o link utili, possibilmente in italiano, dove vengono descritti i passaggi?

Tutto quello che sò è che se vengono incluse, sono subroutine che vengono richiamate automaticamente con il comando e la modalità dichiarata al suo interno, diventando così parte integrante del codice.

Qualcuno ha info su questo argomento? Grazie!

Un saluto a tutti.

:astonished:
Ho provato lo sketch della matrice "AMR_LedMatrixTest" che hai postato ed ho riscontrato lo stesso problema che ho avuto durante i miei primi test (cioè sembra un albero di natale).

PS: Per poter vedere qualcosa ho inserito un ritardo tra una visualizzazione e l'altra:

void loop() {
writeCell(cnt, value);
cnt++;
if (cnt == NUM_ROWS*NUM_COLS) {
cnt = 0;
value = 1 - value;
}
delay(200);
}

Occorre rivedere il codice della matrice ed utilizzare INPUT / OUTPUT per evitare le accensioni.

Ciao.

Ah, già, naturalmente era necessario inserire un delay alla fine di loop() :stuck_out_tongue:

Quindi se ho ben capito senza modificare il pinmode ci sono delle accensioni "spurie" nel passaggio da un led all'altro ?

Per quanto riguarda la libreria, il codice della matrice è già scritto in quell'ottica :wink:

In allegato lo sketch modificato in modo che utilizzi il pinMode come faceva la tua funzione verirow().
Compilato, non provato...

AMR_LedMatrixTest_pinmode.ino (1.31 KB)

...e infine ecco il codice convertito in una classe (in allegato).

Ho un dubbio: nella funzione allOff() tutti i pin vengono messi in modalità INPUT. E' necessario anche scrivere un valore LOW ? (purtroppo non ho una matrice di led come la tua sotto mano. Spero di avere il tempo di costruirne una, magari anche solo 2x2... :~ )

Per quanto riguarda come scrivere una libreria per Arduino:

http://www.arduino.cc/playground/Code/Library

E' necessario (IMVHO) conoscere almeno le basi della programmazione ad oggetti.

AMR_LedMatrixClassTest.zip (1.61 KB)

:stuck_out_tongue: Fantastico !!
Ora si che funziona !!!!

Accensione del primo gruppo di led, poi del secondo e a ciclo continuo, un led alla volta per tutti e 32.

Bene provvedo all'upgrade del codice base R05G e lo posto sul FABLAB, così dovrei snellire non di poco lo sketch.

Per la libreria, credo mi tocchi aspettare ancora un pò per capire il meccanismo.

Grazie.
Ciao.

:slight_smile:

:stuck_out_tongue:
Un saluto a tutta la comunità.

Ho postato sul sito del FABLABTorino (http://www.fablabtorino.org/portfolios/arduomemoryreminder/) la nuova versione R05G con gli aggiornamenti legati alla selezione della lingua in eprom, completamento descrizione delle funzioni ed inserimento della matrice per la gestione dei led, consigliata da tuxduino (con piccoli ritocchi per il codice) che permette allo sketch di snellirsi guadagnando circa 3K in compilazione.

PS.: C'è qualcuno che ha provato a realizzare il progetto?

Ciao.

Ciao, osservando l'integrazione di writeCell() mi ha colpito l'uso misto che fai delle variabili globali e degli argomenti di funzione.

Cerco di spiegarmi meglio con un esempio "stupido".
Supponiamo di avere una funzione somma() che appunto ritorna il risultato della somma di due interi:

int somma(int a, int b) {
    return a + b;
}

Questa funzione è in un certo senso "autocontenuta", cioè

  1. se ne può spiegare il funzionamento senza far riferimento ad altro codice
  2. può essere utilizzata così com'è in qualunque sketch senza alcuna modifica.

Ora immaginiamo di usare questa funzione in un programma complesso, in cui ad esempio abbiamo due variabili livello1 e livello2, e una terza variabile livelloTotale che rappresenta la somma dei due livelli. Potremmo integrare la funzione somma in questo modo:

int livello1;
int livello2;
int livelloTotale;

void sommaLivelli() {
    livelloTotale = livello1 + livello2;
}

Utilizzo:

// leggi livelli attuali
livello1 = readLevelSensor(...);
livello2 = readLevelSensor(...);
// calcola nuovo livello totale
sommaLivelli();
// visualizza il nuovo livello totale
lcd.print(livelloTotale);

Nota che la funzione sommaLivelli(), a differenza di somma(), non è generale. Per comprenderla è necessario fare riferimento a variabili definite al di fuori di essa. Inoltre non è possibile copiarla così com'è in altri programmi, a meno di non introdurre anche in essi le varaibili livelloTotale, livello1 e livello2, che probabilmente non avrebbero senso al di fuori del loro contesto originale.

Il modo corretto di utilizzare somma() è invece:

// leggi livelli attuali
livello1 = readLevelSensor(...);
livello2 = readLevelSensor(...);
// calcola nuovo livello totale
livelloTotale = somma(livello1, livello2);
// visualizza il nuovo livello totale
lcd.print(livelloTotale);

Quindi la morale è:

  • non utilizzare variabili globali per passare argomenti ad una funzione né per ritornare il valore calcolato al programma principale
  • le funzioni debbono essere il più possibile indipendenti dal programma in cui sono inserite
    (naturalmente si tratta di princìpi guida che vanno poi interpretati caso per caso...)

Per concludere, tornando all'integrazione di writeCell(), nella prospettiva di utilizzare box medicine con diverso numero di righe e colonne è meglio lasciare la writeCell() così come l'ho scritta io, e invece di "fonderla" con verirow(), utilizzarla all'interno di verirow() in questo modo:

verirow() {
calcola il numero della cella e il numero del paziente in base al numero di medicina
writeCell(numero cella, numero paziente)
}

Così la writeCell() rimane legata soltanto al modo in cui la matrice di led è costruita e collegata all'arduino, mentre la verirow() è legata ai dati e alle convenzioni del programma (ad esempio il fatto che le medicine sono numerate da 1 a 33, le 1-16 son di un paziente e le 17-33 di un altro), e interfaccia i due "mondi" convertendo il numero di medicina selezionato in valori "digeribili" dalla writeCell(), cioè a partire dal numero di medicina calcola il numero della cella e quale dei due led accendere.

]:smiley:
Untarrabbià!!!! tuxduino!!!!

Ripristinata in originale la matrice WriteCell con gli aggiustamenti del caso su verirow.

Ieri ho fatto le cose un pò di fretta ! Sorry =(

void verirow() {
// select patient 1 or 2 and adj number of medicine
if(med[0] >16){cnt=med[0]-17; value=0;} else {cnt=med[0]-1; value=1;}
writeCell(cnt,value);
}

// function by tuxduino
// cellNumber: 0..ROW*COLS
// value: HIGH or LOW
void writeCell(byte cellNum, byte value) {
byte row;
byte col;

row = cellNum / NUM_COLS;
col = cellNum % NUM_COLS;

allOff();

pinMode(colPins[col], OUTPUT);
digitalWrite(colPins[col], value);

pinMode(rowPins[row], OUTPUT);
digitalWrite(rowPins[row], !value);
}

PS.: Verificata con l'hardware ed aggiornata con la versione R05G1 :stuck_out_tongue:

eheh, vedi com'è tutto più elegante ? :smiley:

Cmq il problema è che certe volte mi prende il raptus del maestrino... scusasse dotto' :stuck_out_tongue:

PS: update: ho raggruppato la parte dei comandi seriali in un'altra libreria, così da togliere un po' di "roba" dal mio primo sketch; ho raccattato un po' di led per fare una matrice almeno 2x2 e ho collegato l'altoparlante su una breadboard. Appena ho capito bene il discorso lampeggio / avviso sonoro lo inserisco nel codice che gira quando è instato di allarme...

Anzi, ne approfitto per farti una domanda: il tono di avviso cambia in base al paziente, alla medicina, ad una combinazione di entrambi ? Grazie!