ARDUINO CON LA SRAM  AS6C4008



Volevo provare la SRAM AS6C4008 con Arduino e per farlo avrei potuto banalmente scrivere un po' di dati nelle locazioni della RAM per poi rileggerle ma ho fatto qualcosa di più; ho progettato un sistema che memorizza nella RAM un ciclo  di un segnale esterno e poi la legge  in loop continuo per ricreare in uscita lo stesso segnale con la stessa ampiezza e frequenza, in più  il segnale memorizzato nella RAM viene sincronizzato con quello esterno.
Il segnale del quale si memorizza un ciclo può avere qualsiasi forma, inoltre una volta posto in uscita, per sincronizzarlo con quello esterno, è necessario che i due abbiano la stessa frequenza, non ha importanza invece la forma d'onda e l'ampiezza (quest'ultima entro certi limiti, infatti essa non può scendere sotto i 200 mVpp valore minimo necessario per poter far funzionare il comparatore correttamente).
Ad esempio nella foto sottostante è visualizzato un segnale memorizzato in RAM di forma triangolare, una volta posto in uscita ho cambiato la forma d'onda del segnale esterno da triangolare a sinusoidale e come si vede i due rimangono comunque  sincronizzati tra loro.



La  foto successiva mostra un segnale memorizzato sinusoidale e quello esterno al quale non è stata cambiata la forma d'onda.



Di seguito un segnale memorizzato di forma sinusoidale e quello esterno al quale è stata cambiata la forma d'onda da sinusoidale a quadrata..



Come funziona? Fare riferimento allo schema seguente.


Il segnale esterno deve  avere le seguenti caratteristiche, ampiezza 5 Vpp e offset 2.5 V, l'offset viene fornito dal mio generatore di segnali, se non disponete di un generatore di segnali che possa fornire l'offset dovrete polarizzare il segnale tramite un partitore resistivo.
Questa polarizzazione serve per far funzionare correttamente l'ADC di Arduino (pin A0). Il segnale oltre ad arrivare al pin A0 deve essere anche letto sulla porta digitale al pin 21 e dato  che il segnale può avere qualsiasi forma e dato che Arduino accetta sulle porte digitali solo segnali di forma quadrata occorre farlo passare per un comparatore (IC1). Prima di giungere al pin 21, però,  occorre diminuirne  la sua



 frequenza della metà tramite flip - flop IC2, vedremo il perché più avanti.
La situazione è raffigurata nella seguente figura dove sono rappresentate le varie tensioni sui punti del circuito indicati da numeri. In questo esempio è stato usato un segnale esterno di forma sinusoidale.


Il segnale memorizzato una volta messo in uscita va convertito in analogico e questo compito lo svolge il DAC  IC3. Analizziamo adesso il programma.
Salto a piè pari le definizioni, le dichiarazioni, il  void setup() per andare direttamente al cuore del programma ovvero al void loop().
La prima istruzione che si incontra alla riga 29 attende che il segnale al pin 21 (segnale 3 in Fig 1)  sia alto. Siccome si deve memorizzare un ciclo completo del segnale esterno occorre avere un riferimento per l'inizio della memorizzazione e per la sua durata, questo riferimento lo da il segnale all'uscita del flip -  flop che ha periodo doppio del segnale, ovvero in metà periodo del segnale 3 (solo quando il segnale 3 è alto) viene campionato  un ciclo completo del segnale 1 (vedi  Fig 1).
Appena il segnale 3 va alto (con un leggero ritardo di tempo in realtà)  il programma esce dal while e arriva alla riga 30, qui c'è una istruzione "for" che ripete il ciclo contenuto nel suo corpo per  la memorizzazione completa del ciclo del segnale 1, ad ogni interazione incrementa  il registro "address" che contiene l'indirizzo della locazione della memoria, il registro alla partenza della conversione  è azzerato.
La prima istruzione che si incontra dolo la "for" è una "if", fintanto che il segnale 3 è alto l'istruzione "if" non esegue la istruzione contenuta  nel suo corpo e il programma va alla  istruzione alla riga  34 che assieme alle quelle successive alle righe  35 e 36 pone sul bus indirizzi della RAM l'indirizzo attuale. Essendo un indirizzo a 19 bit occorrono tre porte a 8 bit, dell'ultima però, la C,  si usano solo 3 bit., occorre fare uno spostamento di bit per la porta B e per la porta C affinché possano essere messi in uscita tutti i bit di ordine superiore.
Nelle righe 37 e 38 viene predisposta la RAM a ricevere il dato da memorizzare, in ordine deve andare basso prima il segnale CE e poi WE, vedi foto sotto:

Alla riga 39 il dato viene  letto dal ADC interno ad Arduino e posto sulla porta L  scrivendolo sulla RAM, si moltiplica il dato convertito per 0.25 per adattare una conversione a 10 bit dell' ADC di Arduino agli 8 bit del DAC esterno.
Subito dopo (riga 40 e 41) viene disabilitata la scrittura in RAM.
Il ciclo di scrittura seguita finché il segnale 3 va basso, quando questo accade la  "if" alla riga 32 esegue le istruzioni presenti nel suo corpo, nello specifico carica il valore 2 nel registro "i" e il programma esce dal loop della "for"; Il ciclo del segnale esterno è stato memorizzato nella RAM.
Alla riga 43 viene predisposta la porta  L come ingresso, le successive due istruzioni, alla riga  44 e 45 predispongono la RAM alla lettura continua del dato al solo cambio dell'indirizzo, ovvero non occorrono altri controlli, vedi figura sotto.

Alla riga 46 il programma setta il registro address a zero, ovvero la RAM inizierà ad essere letta dalla sua prima locazione. Alla riga 47 pone il valore 1 nel registro "i", dopo vedremo a che serve questo registro.
Alla riga 48 l'istruzione "while" attende che il livello del segnale 3 vada alto, questo serve per sincronizzare il momento nel quale il segnale 3 va alto a quello nel quale inizia la lettura nella RAM.
Alla riga 49 c'è un'altra istruzione "while", questa crea un loop infinito perché la RAM, da questo momento in poi, verrà continuamente letta senza alcuna interruzione.
Alla riga 51 troviamo l'istruzione "if" che confronta il livello del segnale 3 con il contenuto del registro "i". Come funziona?.
Ammettiamo che il segnale 3 vada alto, la "if" controlla il livello del segnale 3 con il contenuto del registro "i" che all'inizio il programma ha impostato a 1. La "if" esegue il suo corpo dove sono contenute la serie di istruzioni per leggere la RAM. Quando il livello del segnale 3 va a zero il programma esegue la "else" nel cui corpo ci sono le istruzioni per azzerare il registro "address" ed il contenuto del registro "i". 
Al prossimo ciclo la "if" confronta il livello del segnale 3 che ora è basso con il contenuto del registro "i" anch'esso basso ed esegue le istruzioni nel suo corpo, in poche parole la lettura non si ferma mai ma in questo modo il segnale esterno sincronizza quello memorizzato in RAM.
Vedi seguente figura.


Le  istruzioni contenute nel corpo della "if" sono simili a quelle già viste prima, ci sono gli indirizzi che vengono posti sulle porte A, B e C e l'incremento del registro "address", in più c'è una istruzione di ritardo in microsecondi, questa serve per far si che il segnale memorizzato in RAM venga posto in uscita con la stessa frequenza di quello esterno. Ho trovato il valore giusto immettendo vari valori fino all'ottenimento del giusto valore che è contenuto nel registro "uS".
Qui sotto i pin della RAM e successivamente la schedina fatta in casa dove l'ho montata.



Qui trovate il file del programma.
Ciao Fabio

HOME