Show Posts
Pages: 1 2 [3] 4 5
31  International / Generale / Re: memorizzazione eventi con data e ora on: February 21, 2013, 05:52:05 am
ciao peppe91,

da quello che dici dovresti scrivere 12 byte per ogni accesso. I primi 6 contengono (giorno, mese, anno, ora, minuti, secondi - un byte per ciascuno); i secondi 6 contengono l'ID del chip RFID.

Mantieni una variabile che ti indica quanti accessi hai già memorizzato. A questo punto troverai i dati del primo accesso tra i bytes 0-11, quello del secondo tra i bytes 12-23... e genericamente, quelli dell'n-esimo tra i bytes [i*12, i*12 + 11] dove la i parte da 0 (il primo accesso ha indice 0).

Ti ribadisco però quello che ti hanno già suggerito. La EEPROM ha un numero di cicli di scrittura "limitato" e rischi di esaurirli in breve tempo. Inoltre, tale memoria non è grandissima (1KB per arduino UNO e 4KB per arduino MEGA). Nel primo caso riesci a memorizzare circa 85 accessi, nel secondo circa 341 che in 48 ore potrebbero essere pochi.

Oltre alla FRAM potresti anche considerare l'uso di una SD.
32  International / Generale / Re: Cosa rende diversi i pin digitali PWM dagli altri ? on: February 19, 2013, 04:26:33 am
acc... non ho fatto in tempo... è arrivato prima... consiglio però di leggere comunque anche l'altra risposta, c'erano ulteriori dettagli.

OT - ma non avrei dovuto ricevere un warning che mi indicava che il thread era stato modificato durante la mia risposta? In un'altra occasione lo avevo visto.
33  International / Generale / Re: Cosa rende diversi i pin digitali PWM dagli altri ? on: February 19, 2013, 04:23:10 am
francamente non conosco la risposta alla tua domanda che però mi incuriosiva... ho cercato quindi "frequenza PWM" su google. Trovi molti risultati.

Il primo di questi http://www.robot-italy.net/roboforum/showthread.php?t=186 è un topic in un altro forum al quale risponde un certo astrobeed - smiley  smiley  smiley

Penso possiamo evitargli di ripetere la spiegazione anche qui... mi pare davvero chiara.
34  International / Generale / Re: Cosa rende diversi i pin digitali PWM dagli altri ? on: February 19, 2013, 03:54:56 am
come ti spiegava astrobeed nel PWM quello che cambia è il duty cycle mentre la frequenza rimane fissa.

L'onda quadra del PWM rimane per un certo periodo di tempo P1 a 1 e per un periodo di tempo P0 (tipicamente diverso...) a 0. La somma di questi due tempi rappresenta il periodo P = P1 + P0 del segnale e quindi la frequenza F sarà uguale a 1/P.

La frequenza del PWM è fissa perchè P è fisso. Quindi P1 e P0 non possono variare arbitrariamente ma sempre in modo che P = P1 + P0 (quindi P1 = P - P0 o viceversa P0 = P - P1).

Spero di aver contribuito a fare chiarezza invece di confondere maggiormente le idee.

35  International / Software / Re: Problema reading seriale e attesa condizione on: February 16, 2013, 04:02:34 am
in pratica quello che vuoi fare, se ho capito bene, è che alla pressione di una delle tre opzioni, per esempio la 'a', l'arduino si metta in attesa di un valore diciamo a n cifre (nel tuo caso credo due ma magari anche una soltanto).

Per prima cosa devi quindi gestire una sorta di stato in cui il tuo software passa nel momento in cui riceve il comando 'a' e fino a quando non riceve un carattere di conferma, per esempio 13 che è il codice ASCII del 'return' della tastiera.

Mentre il software si trova in questo stato dovrà accettare i caratteri numerici 0-9 (ASCII da 48 a 57) e magari il carattere di cancellazione (backspace, non ricordo l'ASCII ma a memoria direi l'8 ). Per quanto riguarda i caratteri numerici, per avere la cifra corrispondente ti basta fare n = c - 48; dove c è il carattere ASCII ricevuto sulla seriale e n è la cifra decimale corrispondente. 

Purtroppo i metodi indicati da lesto temo non vadano bene. Infatti si riferiscono alla ricezione di dati binari mentre tu invece invii caratteri ASCII e vuoi ottenere non una stringa (il terzo caso da lui proposto) ma l'intero corrispondente. Avevo già proposto una possibile implementazione in questo thread: http://arduino.cc/forum/index.php/topic,137925.msg1036592.html#msg1036592 . Lì i caratteri arrivavano da una tastiera e tu invece li ricevi dalla seriale. Tuttavia, dopo la conversione ASCII/decimale che ti ho indicato, la questione diventa la stessa.

Ricapitolando il codice diventerebbe qualcosa del genere (ti ricordo che non l'ho provato...)

Code:

boolean flagmenu = true;
int byteInArrivo = 0; // per iniziare la trasmissione seriale
int serial =0;

void setup( )
{
   Serial.begin(9600); // apertura porta seriale, impostazione velocità di
                                // trasmissione dati a 9600bps

   prompt()
}

void loop( )
{
 
   if (Serial.available()>0)
   {
      byteInArrivo = Serial.read( );
     
      if (flagmenu)
      {
         switch (byteInArrivo)
         {
              case 97:
                 Serial.print("Hai premuto a");
                 flagmenu=false;
                 break;
              case 98:
                 Serial.print("Hai premuto b");
                 // qui chiami la funzione da eseguire quando viene premuto b
                 break;
              case 99:
                 Serial.print("Hai premuto c");
                 // qui chiami la funzione da eseguire quando viene premuto c
                 break;
              default:
                 Serial.print("Comando sconosciuto");
                 break;
         }
     
         delay(2000); // serve per dare 2 secondi di tempo per vedere l'eventuale output della funzione richiesta
                            // magari è inutile o vuoi sostituirlo con qualcos'altro
         prompt();
      }
      else
      {
         // qui dovresti inserire il pezzo di codice che gestisce la lettura del parametro partendo dal valore contenuto in byteInArrivo
         if (byteInArrivo == 13)
         {
             // ora una tua variabile conterrà il valore ricevuto dalla seriale
             // ritorni nello stato di attesa di un comando
             flagmenu = true;
         }
      }
}

void prompt()
{
   Serial.println("\E[H\E[2J" );  //Clear Screen in PuTTY
   Serial.println("Scegli tra le seguenti opzioni:");
   // perchè le delay? A cosa servono?
   //delay(5);
   Serial.println("a - Leggi x");
   //delay(5);
   Serial.println("b - Leggi y");
   //delay(5);
   Serial.println("c - Leggi z");
   //delay(5);
   Serial.print("\n");
   //delay(5);
}

Non me ne volere... volutamente non ho scritto il pezzo di codice che ricostruisce il valore del parametro per due motivi. Il primo è che richiede un minimo di attenzione in più e magari qualche test. Il secondo è che condivido il suggerimento di leo72. Ho provato a darti qualche spunto ma poi, se vuoi veramente imparare a programmare, l'unico modo che conosco è quello di "perderci le nottate...". Non è mancanza di disponibilità da parte degli amici del forum è solo l'unica strada possibile.

Ciò premesso, se hai ancora altri dubbi, chiedi pure.

Ciao.
Vittorio.
36  International / Software / Re: Problema reading seriale e attesa condizione on: February 13, 2013, 06:47:37 am
ciao

ho messo la stampa del menu in una funzione per poterlo richiamare sia da setup() che da loop(). L'ho messo anche in setup proprio per evitare che l'utente possa scrivere qualcosa sulla seriale prima della stampa del menu.

In generale però l'aspetto importante è un'altro. Nel codice che avevi scritto tu, bloccavi l'esecuzione di loop in attesa di un carattere sulla seriale. Questo magari funziona pure ma mi sembra un approccio meno "generico". Nel codice che ho proposto io invece il controllore esegue sempre il loop e quindi tu potrai fargli fare altre cose ad ogni ciclo in attesa che arrivi un comando.

Ti faccio un esempio. Immagina di voler realizzare un termostato che legga all'infinito una temperatura ed attivi un relè quando questa è più bassa di una certa soglia. In più, come hai fatto tu, ogni volta che sulla seriale arriva il carattere 'a' mi risponde con l'ultima temperatura letta, quando arriva 'b' mi risponde con la media, quando arriva 'c' mi cambia di stato al relè a prescindere dalla temperatura (magari quest'ultimo esempio andrebbe approfondito per non essere assurdo...).

Con il mio approccio puoi inserire il codice per la lettura del sensore e per l'attivazione del relè all'interno del loop (prima o dopo l'if sulla Serial.Available non ha molta importanza...) ed essere sicuro che sia la gestione del sensore e del relè sia la gestione della seriale avvenga "contemporaneamente" (o almeno che sembri così).
37  International / Software / Re: Problema reading seriale e attesa condizione on: February 13, 2013, 03:46:21 am
Ti scrivo qualche riga senza averla provata... usala solo come punto di partenza

Code:
int byteInArrivo = 0; // per iniziare la trasmissione seriale
int serial =0;

void setup( )
{
   Serial.begin(9600); // apertura porta seriale, impostazione velocità di
                                // trasmissione dati a 9600bps

   prompt()
}

void loop( )
{
 
   if (Serial.available()>0)
   {
      byteInArrivo = Serial.read( );
     
      switch (byteInArrivo)
      {
           case 97:
              Serial.print("Hai premuto a");
              // qui chiami la funzione da eseguire quando viene premuto a
              break;
           case 98:
              Serial.print("Hai premuto b");
              // qui chiami la funzione da eseguire quando viene premuto b
              break;
           case 99:
              Serial.print("Hai premuto c");
              // qui chiami la funzione da eseguire quando viene premuto c
              break;
           default:
              Serial.print("Comando sconosciuto");
              break;
      }
     
      delay(2000); // serve per dare 2 secondi di tempo per vedere l'eventuale output della funzione richiesta
                         // magari è inutile o vuoi sostituirlo con qualcos'altro
      prompt();
   }
}

void prompt()
{
   Serial.println("\E[H\E[2J" );  //Clear Screen in PuTTY
   Serial.println("Scegli tra le seguenti opzioni:");
   // perchè le delay? A cosa servono?
   //delay(5);
   Serial.println("a - Leggi x");
   //delay(5);
   Serial.println("b - Leggi y");
   //delay(5);
   Serial.println("c - Leggi z");
   //delay(5);
   Serial.print("\n");
   //delay(5);
}
38  International / Generale / Re: 4 Arduino Master Slave in RS485 on: February 11, 2013, 10:24:32 am
no, no, aspetta... come ho scritto, questa cosa l'ho inserita solo in questo sketch di prova e soltanto perchè all'inizio ho fatto qualche prova collegando lo slave solo in un secondo momento. Fatto così, il master mi interrogava sempre lo stesso slave fino a che non lo collegavo.

Gli sketch che ho postato non vogliono essere un esempio di funzionamento reale, ma solo un punto di partenza per vedere due arduino che parlano tra loro secondo una architettura master/slave, cioè con uno che interroga e l'altro che risponde.

Avrai notato che non viene nemmeno gestito un timeout entro il quale lo slave interrogato deve rispondere.

Come ho scritto, il protocollo reale deve provvedere per esempio ad isolare lo slave che non risponde ossia deve evitare di interrogarlo ulteriormente. In particolare, il comportamento potrebbe essere il seguente:

- quando uno slave non risponde entro pochissimi ms, l'evento viene ignorato per un certo numero di volte (per esempio 3) per gestire il caso in cui lo slave è momentaneamente occupato (se questo è possibile).
- se non risponde per 3 tentativi consecutivi, viene messo in stato "DOWN" ed il master passa ad interrogarlo solo ad intervalli molto più lunghi, per esempio ogni 10 secondi (per implementare una sorta di plug&play) oppure su richiesta di una supervisione (per gestire il collegamento di un nuovo slave in maniera manuale).
39  International / Generale / Re: 4 Arduino Master Slave in RS485 on: February 11, 2013, 09:32:44 am
ecco invece il codice dello slave.

Non avendo 16 arduino, semplicemente il codice risponde sempre a prescindere dal destination address. Tanto per customizzare la risposta, il byte di dati è uguale all'ID slave moltiplicato per due.

Il byte di checksum viene calcolato (sia nel master che nello slave) ma non viene controllato.

Il codice però attende un byte 255 per memorizzare i byte ricevuti.

Code:
// Protocollo
// 0 - sender address
// 1 - destination address
// 2 - command
// 3 - data
// 4 - checksum

int pinEnableWrite = 5;
byte command = 2;
byte idxSlave;
byte idxRead;
byte buffer[6];

void setup()
{
Serial.begin(9600);
Serial1.begin(115200);

pinMode(pinEnableWrite, OUTPUT);     
digitalWrite(pinEnableWrite, LOW);

idxRead = 0;
}

void loop()
{
if (Serial1.available())
{
buffer[idxRead] = Serial1.read();
//if (idxRead == 0) Serial.print("Richiesta: ");
//Serial.print(buffer[idxRead], DEC);
//Serial.print(" ");
if (idxRead > 0  ||  buffer[0] == 255) idxRead++;
}

if (idxRead == 6)
{
//Serial.println(" ");
//delay(10);

idxSlave = buffer[2];
buffer[0] = 255;
buffer[1] = idxSlave;
buffer[2] = 0;
buffer[3] = command;
buffer[4] = idxSlave * 2;
buffer[5] = buffer[1] ^ buffer[2] ^ buffer[3] ^ buffer[4];

RS485Write(buffer, 6);

idxRead = 0;
}

delay(1);
}

void RS485Write(byte* packet, byte len)
{
UCSR1B &= ~(1<<RXEN0);  //disable RX   
UCSR1A = UCSR1A |(1 << TXC0); 
Serial1.flush();

digitalWrite(pinEnableWrite, HIGH);
Serial1.write(packet, len);

while (!(UCSR1A & (1 << TXC0))); // attendi fine trasm.

digitalWrite(pinEnableWrite, LOW);
UCSR1B |= (1<<RXEN0);   //enable RX
}
40  International / Generale / Re: 4 Arduino Master Slave in RS485 on: February 11, 2013, 09:28:25 am
Come promesso ho scritto un paio di sketch, uno per il master e uno per lo slave per fare qualche prova. Si tratta di poche righe di codice tanto per cominciare a partire. In particolare, a mio avviso bisogna rivedere il byte di start (attualmente un solo byte sempre 255) per fare in modo che la sequenza di start non possa presentarsi all'interno del pacchetto.

Il codice simula l'interrogazione di 16 slaves (numerati da 1 a 16 perchè 0 è il master...). Quando interroga uno slave, attende la risposta per 5 secondi, se non la riceve invia nuovamente la richiesta allo stesso slave. Questo è utile solo per questo semplice sketch, il protocollo finale dovrà funzionare in maniera diversa (tipo isolare lo slave che non risponde...).

Il protocollo è simile a quello già discusso. Probabilmente un solo byte di dati è poco ma, ancora una volta, è solo per provare.

La funzione RS485Write disabilita la ricezione della seriale e attiva il pin che abilita la trasmissione. Attende quindi la fine della trasmissione per ripristinare il funzionamento in ricezione.

Ho usato un Arduino Mega sfruttando la Serial2. Lo slave invece utilizza Serial1. Non c'e' alcun motivo per fare questo. Nel mio caso dipende semplicemente dal fatto che ho usato due shields autocostruiti in tempi diversi sui quali avevo utilizzato due seriali diverse. Basta modificare lo sketch facendo attenzione a modificare anche i flag utilizzati nella RS485Write.

Ecco il codice del master. Scrivo quello dello slave in un post successivo.

Code:
// Protocollo
// 0 - start = 255
// 1 - sender address
// 2 - destination address
// 3 - command
// 4 - data
// 5 - checksum

int pinEnableWrite = 5;
byte idxSlave;
byte idxRead;
byte command = 1;
bool nextRequest;
unsigned long lastRequest;
unsigned long last1;

void setup()
{
Serial.begin(9600);
Serial2.begin(115200);

pinMode(pinEnableWrite, OUTPUT);     
digitalWrite(pinEnableWrite, LOW);

idxSlave = 1;
idxRead = 0;

nextRequest = true;
}

void loop()
{
if (nextRequest)
{
                            if (idxSlave == 1) last1 = millis();
               
//Serial.print("Richiesta slave: ");
//Serial.println(idxSlave, DEC);

byte buffer[6];
buffer[0] = 255;
buffer[1] = 0;
buffer[2] = idxSlave;
buffer[3] = command;
buffer[4] = 0;
buffer[5] = buffer[1] ^ buffer[2] ^ buffer[3] ^ buffer[4];

RS485Write(buffer, 6);

nextRequest = false;
lastRequest = millis();
}
else
{
unsigned long Now = millis();
if (Now - lastRequest > 5000)
{
nextRequest = true;
}
else
{
if (Serial2.available())
{
byte B = Serial2.read();

//if (idxRead == 0) Serial.print("Risposta: ");

//Serial.print(B, DEC);
//Serial.print(" ");

idxRead++;
if (idxRead == 6)
{
//Serial.println(" ");

idxRead = 0;

idxSlave++;
if (idxSlave == 17)
{
Now = millis() - last1;
Serial.print("Durata ciclo = ");
Serial.println(Now, DEC);
idxSlave = 1;
}

nextRequest = true;
}
}
}
}

delay(1);
}

void RS485Write(byte* packet, byte len)
{
UCSR2B &= ~(1<<RXEN0);  //disable RX   
UCSR2A = UCSR2A |(1 << TXC0); 
Serial2.flush();

digitalWrite(pinEnableWrite, HIGH);
Serial2.write(packet, len);

while (!(UCSR2A & (1 << TXC0))); // attendi fine trasm.

digitalWrite(pinEnableWrite, LOW);
UCSR2B |= (1<<RXEN0);   //enable RX
}


41  International / Software / Re: rs422 full duplex on: February 05, 2013, 05:28:55 am
Quote
ma con xbee e un mash network non si potrebbe fare?

Io propenderei per il CAN suggerito da astrobeed. Mi pare più economico e meno soggetto a distrubi esterni. Confesso che non conosco la sensibilità di xbee ai distrurbi, ma poichè si tratta di una applicazione abbastanza mission critical (bruschetta parlava di un valore di migliaia di euro...) eviterei di correre rischi.

Rifletterei inoltre ancora un po' sulla soluzione I2C. Dovendo controllare un acquario, quindi un sistema relativamente piccolo dove i diversi arduino saranno probabilmente posizionati molto vicini tra loro (se poi mi sbaglio, bruschetta mi correggerà...) magari la lunghezza del bus non è così critica. Inoltre esiste il P82B715 che è un I2C extender che potrebbe aiutare qualora fosse necessaria una lunghezza del bus maggiore.
42  International / Generale / Re: 4 Arduino Master Slave in RS485 on: February 05, 2013, 04:48:11 am
Quote
Allora dopo tutto questo parlare peché non ci uniamo in u n unico gruppo e iniziamo
a mettere le basi per un "simple protocol"

Qualche tempo fa avevo fatto qualche prova con un paio di Arduino Mega (scelti sopratutto per la maggiore capacità di memoria...) ed un paio di SN75716BP per creare una RS485. Appena ho un po' di tempo rimetto insieme gli sketch di prova che avevo fatto e comincio a postarli.

Ciao.
Vittorio.
43  International / Generale / Re: 4 Arduino Master Slave in RS485 on: February 04, 2013, 06:03:12 am
E ritorno anche al mio dubbio...

Quote
50 ms sono una eternità, il tempo medio per la transazione master/slave è 4-5 ms, il timeout mediamente si imposta tra 10-20 ms ed è una condizione di errore

certo, con 4-5 ms i conti tornano... ho però qualche dubbio. In questo tempo, il master deve inviare la richiesta e lo slave deve rispondere; pensi che sia fattibile con Arduino? Appena ho un po' di tempo ci provo.

Quote
E poi non è che il master debba terminare tutto il ciclo di interrogazioni quando deve spedire un comando.

questo mi piace  smiley In pratica appena riceve una variazione da uno slave esegue la logica di controllo per verificare se deve comandare qualcosa ed invia i comandi necessari.

Quote
Il controllo degli slave sarà fatto nei momenti di idle del sistema.

questo invece non lo capisco. Mi pare, come dice anche astrobeed, che il sistema interroghi sempre gli slaves, altrimenti come fa a sapere se c'e' stata una variazione o meno. E comunque immagino che la logica di controllo venga eseguita in un tempo brevissimo; credo che il master passi la maggior parte del tempo ad interrogare gli slaves.

Ciao.
44  International / Generale / Re: 4 Arduino Master Slave in RS485 on: February 04, 2013, 04:27:27 am
Ciao,

innanzitutto provo a rispondere alla domanda di peppe e pietro. Mi pare giusto dato che mi sono inserito di "prepotenza" nel thread.

Ovviamente la mia risposta potrebbe essere discussa insieme proprio perchè non sono sicuro che l'architettura che ho in mente sia quella corretta.

Come ho già detto, a differenza di peppe, io non immagino una logica di controllo sugli slaves perchè questo mi costringerebbe ad aggiornarne il firmware in caso di modifiche. Preferirei avere una logica centralizzata con gli slaves che fanno solo da sensori/attuatori.

Ciò premesso penso che il sistema dovrebbe funzionare in questo modo.

1 - il master chiede ad ogni slave il suo stato (per esempio lo stato dei pulsanti ad esso collegati oppure l'ultimo valore di temperatura letto)
2 - conoscendo lo stato di uno slave invia un comando ad uno o più slaves (per esempio sullo slave 2 è stato premuto il pulsante 1 e comanda allo slave 3 di chiudere il relè 2 ed allo slave 4 di chiudere il relè 3)

Dal punto di vista del protocollo seriale, pensando a qualcosa di simile a quello indicato all'inizio di questo thread, il master chiede lo stato ad ogni slave inviando un pacchetto con un determinato codice comando (per esempio RichiestaStatoInput = 1). Lo slave risponde con un pacchetto con codice comando RispostaStatoInput = 2. In questo caso deve comunicare un valore e lo fa utilizzando i bytes del pacchetto predisposti per eventuali dati. Il master deve quindi comandare la chiusura dei relè e lo fa inviando al relativo slave un pacchetto con codice comando ImpostaStatoOutput = 3 utilizzando ancora i bytes di dati per comunicare il valore di Stato che vuole impostare.

Ovviamente si tratta solo di una traccia, il protocollo andrebbe approfondito nel dettaglio anche in funzione di quello che si deve implementare.

Ciao.
Vittorio.
45  International / Generale / Re: 4 Arduino Master Slave in RS485 on: February 01, 2013, 09:31:25 am
questo non lo sapevo... è già un ottimo punto di partenza.

Tuttavia mi pare che il problema iniziale rimanga... anche se abbassiamo a 30 il limite massimo dobbiamo comunque considerare che 10ms erano soltanto un esempio fatto per mostrare come anche con tempi così ridotti, si raggiungono tempi totali considerevoli. Se immaginiamo un tempo più realistico, per esempio 50ms, torniamo nuovamente a 1,5 secondi per interrogare 30 slaves.

Pages: 1 2 [3] 4 5