Alcuni problemi nvSRAM 23LCV1024, uso libreria di gpb01

Buongiorno a tutti.
Ho comprato il chip (DIP) 23LCV1024 su aliexpress (spero non sia fallato).
Creato mio modulino collegamento SPI:



Potete vedere che le saldature non mi sono venute bene, però...
usando la libreria mi capita una cosa strana, sempre uguale, non randomica
domanda 1. se fossero problemi sul segnale SPI non dovrebbero essere random?

Ora usando il programma di test della libreria (tolto alcune righe vuote x accorciarlo x forum), arduino Uno R3:

/* Sample usage of NVSRAM library with different Arduino data types.
   Guglielmo Braguglia - Dec. 2020  */
#include <NVSRAM.h>
/* Leave the following #define uncommented if you want to do a complete 
   WRITE/READ BACK cycle. Comment if you want only to da a READ BACK cycle
   to verify battery data retention */
#define WR_RD
/* Lave the following #define uncommented if you want to use the automatic
   default SPI bus initialization. Comment if you want to use a manual SPI
   bus initialization with specific parameters */
#define SPI_INIT
/* ------------------------------------------------------------------------ */
#ifdef SPI_INIT
NVSRAM myNVSRAM ( 10 );
#else
NVSRAM myNVSRAM ( 10, false );
#endif

void setup ( void ) {
   byte  b = 0;
   int   i = 0;
   float f = 0.0;
   byte  a[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
   struct myStruct {
      byte  by = 0;
      int   in = 0;
      float fl = 0.0;
      byte  ar[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
   } s;
   unsigned long tStart = 0, tEnd = 0;
   unsigned int  block_crc = 0;
   byte          j;

   delay ( 500 );
   Serial.begin ( 115200 );
#ifndef SPI_INIT
   SPI.begin();
   SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
   myNVSRAM.begin();   
#endif
#ifdef WR_RD
   Serial.println ( "Demo program WRITE/READ begins ..." );
   /* Erase all the NVSRAM memory   */
   tStart = micros();
   myNVSRAM.erase();
   tEnd = micros();
   Serial.print ( "Memory erased in " );
   Serial.print ( tEnd - tStart );
   Serial.print ( " µsec; " );
   Serial.print ( "Bytes erased: " );
   Serial.print ( myNVSRAM.length() );
   Serial.print ( ", µsec per byte≈ " );
   Serial.println ( ( tEnd - tStart ) / myNVSRAM.length() );
   Serial.println( );
#else
   Serial.println ( "Demo program READ ONLY begins ..." );
#endif
#ifdef WR_RD
   b = 127;
   myNVSRAM.write ( 0x0000, b );
#endif
   b = myNVSRAM.read ( 0x0000 );
   Serial.print ( "Byte b reading with read (expected 127): " );
   Serial.println ( b );
   b = myNVSRAM[ 0 ];
   Serial.print ( "Byte b reading with [] (expected 127): " );
   Serial.println ( b );
#ifdef WR_RD
   i = -127;
   myNVSRAM.put ( 0x0001, i );
#endif
   myNVSRAM.get ( 0x0001, i );
   Serial.print ( "Integer i reading with get (expected -127): " );
   Serial.println ( i );
#ifdef WR_RD
   f = 127.12;
   myNVSRAM.put ( 0x0003, f );
#endif
   myNVSRAM.get ( 0x0003, f );
   Serial.print ( "Float f reading with get (expected 127.12): " );
   Serial.println ( f );
#ifdef WR_RD
   for ( j = 0; j < 10; j++) a[j] = j;
   myNVSRAM.put ( 0x0007, a );
#endif
   myNVSRAM.get ( 0x0007, a );
   Serial.print ( "Array a reading with get (expected 0..9): " );
   for ( j = 0; j < 10; j++ ) {
      Serial.print ( a[j] );
      if ( j < 9 ) Serial.print ( ", " );
   }
   Serial.println ( );
#ifdef WR_RD
   s.by = 127;
   s.in = -127;
   s.fl = 127.12;
   for ( j = 0; j < 10; j++) s.ar[j] = j;
   myNVSRAM.put ( 0x0011, s );
#endif
   myNVSRAM.get ( 0x0011, s );
   Serial.println ( "Structure s reading with get ..." );
   Serial.print ( "  - byte by value (expected 127): " );
   Serial.println ( s.by );
   Serial.print ( "  - integer in value (expected -127): " );
   Serial.println ( s.in );
   Serial.print ( "  - float fl value (expected 127.12): " );
   Serial.println ( s.fl );
   Serial.print ( "  - byte array ar value (expected 0..9): " );
   for ( j = 0; j < 10; j++ ) {
      Serial.print ( s.ar[j] );
      if ( j < 9 ) Serial.print ( ", " );
   }
   Serial.println ( );
   Serial.println ( );
   block_crc = myNVSRAM.crc ( 0, 34 );
   Serial.print ( "CRC16 of first 34 bytes (expected 12711): " );
   Serial.println ( block_crc );
   Serial.println ( );
   Serial.println ( "Test completed." );
#ifndef SPI_INIT
   SPI.endTransaction();
#endif
}
void loop ( void ) {}

ottengo su serial monitor:

Demo program WRITE/READ begins ...
Memory erased in 444684 µsec; Bytes erased: 131071, µsec per byte≈ 3

Byte b reading with read (expected 127): 127
Byte b reading with [] (expected 127): 127
Integer i reading with get (expected -127): -127
Float f reading with get (expected 127.12): 127.12
Array a reading with get (expected 0..9): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

Structure s reading with get ...
  - byte by value (expected 127): 127
  - integer in value (expected -127): -127
  - float fl value (expected 127.12): 127.12
  - byte array ar value (expected 0..9): 0, 1, 2, 3, 4, 5, 6, 7, 65, 66

CRC16 of first 34 bytes (expected 12711): 38608

Test completed.

!! diverso da ieri... forse i collegamenti hw fanno proprio pena. Ieri non funzionava float e array

SW:
Però... visto che ieri sembrava funzionare solo la put di byte (la put è overloaded usando template del C++), ho fatto un tentativo di usare solo il comando put di un byte ed ottengo una cosa strana (c'e' qualche errore nel mio C++ ?? ):

   Serial.print( "b=" );       // scrittura da 0 a x per 0x60 a 0x80
   b=0;
   for(i=0x0060; i<=0x0080;i++) 
   { Serial.print(b); Serial.print( ','); 
     myNVSRAM.put ( i, b );
     b=b+1;
   }

Su serial monitor:
b=0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
A video, sembra che la variabile b si "perda" il valore

se passo attraverso altra variabile, non ho questo effetto strano:

  Serial.print( "b=" );
   j=0;b=0;
   for(i=0x0060; i<=0x0080;i++) 
   { b=j; 
    Serial.print(b); Serial.print( ','); 
     myNVSRAM.put ( i, b );
     j=j+1;
   }

Serial monitor:
b=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,
Sembra quasi che la put() 'sbarella' la variabile b
domanda 2. Ho scritto qualcosa di sbagliato ?

Aggiungi, come da datasheet, i condensatori sull'alimentazione che nell' articolo originale mancavano ...

Guglielmo

1 Like

Difficile ... comunque, questo è quello che fa la put():

      template< typename T > const T &put ( uint16_t addr, const T &t ) {
         uint16_t t_size = sizeof ( T );
         //
         digitalWrite ( ssPin, LOW );
         SPI.transfer ( NVSRAM_WRITE );
         SPI.transfer16 ( addr );
         SPI.transfer ( ( void* ) &t, t_size );
         digitalWrite ( ssPin, HIGH );
         return t;
      }

Guglielmo

Dalla foto sembra ci sia un corto sul connettore tra i pin 1 e 2:


controlla, forse è solo l'angolazione della foto che inganna.

Ciao, Ale.

Credo sia solo un pelo di gatto (ho la casa piena :laughing:
Comunque verifico

1 Like

Ok, provo a metterlo.

Vista. Quindi non vedete nulla di strano nel mio ciclo di scrittura tramite variabile b e put di byte senza passaggio in j.

Riprovato a togliere passaggio con variabile j e di nuovo effetto strano. Ma non me lo spiego. Anche a me pare incredibile.

Mi hai fatto riprendere in mano la libreria e ... la sto provano su UNO R4 ...

Ho dovuto fare alcune modifiche per cose di cui non avevo tenuto conto inizialmente:

  1. ho dovuto mettere una mia routine per il calcolo del crc16 visto che, all'epoca, usavo quella standard della AVR libc che ... NON c'è per Renesas. Ho uniformato tutto alla nuova, ma, ovviamente, il valore del CRC è diverso (uso un altro polinomio) quindi ... NON c'è retro compatibilità sul CRC.
  2. Mi sono reso conto che usare i "tipi" standard provoca i soliti casini ('int' su AVR = 2 bytes, 'int' su UNO R4 = 4 bytes) ed ho modificato il tutto (esempio e lib) per usare <stdint.h> (unit8_t, int16_t, ecc.).

Per il resto ... sembra funzionare tutto anche sulla R4 ...

Demo program WRITE/READ begins ...
Memory erased in 284641 µsec; Bytes erased: 131071, µsec per byte≈ 2

uint8_t b reading with read (expected 127): 127
uint8_t b reading with [] (expected 127): 127
int16_t i reading with get (expected -127): -127
Float f reading with get (expected 127.12): 127.12
Array a reading with get (expected 0..9): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Structure s reading with get ...
  - uint8_t by value (expected 127): 127
  - int16_t in value (expected -127): -127
  - float fl value (expected 127.12): 127.12
  - uint8_t array ar value (expected 0..9): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

CRC16 of first 34 bytes (expected 60577): 60577

Test completed.


Demo program READ ONLY begins ...
uint8_t b reading with read (expected 127): 127
uint8_t b reading with [] (expected 127): 127
int16_t i reading with get (expected -127): -127
Float f reading with get (expected 127.12): 127.12
Array a reading with get (expected 0..9): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Structure s reading with get ...
  - uint8_t by value (expected 127): 127
  - int16_t in value (expected -127): -127
  - float fl value (expected 127.12): 127.12
  - uint8_t array ar value (expected 0..9): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

CRC16 of first 34 bytes (expected 60577): 60577

Test completed.

Guglielmo

@nid69ita:

Un altra cosa ... immagino tu faccia il collegamento "volante" del bus SPI, cosa che, con un bus che viaggia a svariati MHz non è il massimo ... NON fare inizializzare il SPI alla libreria ma inizializza tu il bus:

// #define SPI_INIT
...
...
#ifndef SPI_INIT

  SPI.begin();
  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
  myNVSRAM.begin();

#endif

... provando a calare quella velocità che è nel SPISettings() e vedendo se, calando, le cose migliorano. :roll_eyes:

Guglielmo

1 Like

Io non sono un esperto e forse sbaglio. Ma, b è definita come bool? Se è cosí, non credo possa avere altri valori che 0 o 1, no?

@bestbit:

Premesso che 'b' dovrebbe essere di tipo 'byte' (uint8_t), comunque considera che il 'bool' ritiene 'false' il valore 0 e 'true' un valore != 0.

Guglielmo

P.S.: mi sono sovrapposto con nid69ita nella risposta :grin:

  1. Solo una idea x la tua libreria. Dare la possibilità di settare i parametri SPI anche se lo fa in automatico ?

  2. nell'esempio, il secondo commento inizia con "Lave" invece di "Leave"

  3. visto il datasheet, ma se per caso il chip non risponde, non c'e' un ritorno dallo SPI per sapere che non ha risposto ?

  4. Per curiosità provare in quel demo:

   Serial.print( "b=" );       // scrittura da 0 a x per 0x60 a 0x80
   b=0;
   for(i=0x0060; i<=0x0080;i++) 
   { Serial.print(b); Serial.print( ','); 
     myNVSRAM.put ( i, b );
     b=b+1;
   }

e vedere se anche a te da valori strani su b (io provato su Uno R3) ??

  1. ho visto che nella begin della libreria, riga con
    SPI.transfer ( 0x40 );
    se il chip è collegato il return è di 255, altrimenti staccando il chip ritorna 64 (0x40)
    presumo che se il comando è "recepito" ritorna 255 (-1) altrimenti c'e' errore.
    Potrebbe essere usato dalla begin per ritornare False se la begin "fallisce" ?
    Un modo per sapere se il chip risponde

Relativamente al tuo punto 3 (secondo), il reference della transfer() riporta chiaramente che NON viene tornato un codice d'errore, ma il carattere ricevuto (in SPI quando trasmetti ricevi anche), quindi ... difficile usarlo per fare diagnostica :wink:

Relativamente al punto 2, vero c'è un errore di battitura, correggo nella versione 1.0.1 (che però sarà incompatibile con la 1.0.0 per ciò che riguarda il calcolo del CRC).

Relativamente la punto 1 ... ridondante, se vuoi cambiare i parametri allora inizializzi tu il bus SPI senza farlo fare alla libreria.

Appena posso, faccio la prova con quel tuo codice :wink:

Guglielmo

Punto 3, in linea teorica invece le puoi usare. Se spedisci 0x40 e spi scrive, allora hai di ritorno lo stesso valore 64. Altrimenti ritorna 255.
Almeno dalla prova "fisica" che ho fatto con Uno R3 quindi atmega328p fa così.

Punto 2, era solo per far fare alla lib tutto, compreso il cambio di parametri. Ovvio, non così "necessario".

P.S. messo condensatore, abbassato velocità a 2000000, non va lo stesso. O le saldature fanno così schifo oppure ho preso una "sola" :laughing:

Non sono d'accordo ... se c'è un chip non si sa bene cosa trasmetta quando gli si invia qualche cosa ... di sicuro, senza chip, probabilmente leggi sempre il pin HIGH (ma non è garantito) e quindi 255, ma, ripeto, non c'è garanzia della cosa ... :roll_eyes:

Guglielmo

:scream: :scream: :scream:

Questo il sorgente della transfer() su AVR nel caso si usi un puntatore a buffer ed una lunghezza (come fa il template della libreria per trattare qualsiasi tipo dato):

inline static void transfer(void *buf, size_t count) {
    if (count == 0) return;
    uint8_t *p = (uint8_t *)buf;
    SPDR = *p;
    while (--count > 0) {
      uint8_t out = *(p + 1);
      while (!(SPSR & _BV(SPIF))) ;
      uint8_t in = SPDR;
      SPDR = out;
      *p++ = in;
    }
    while (!(SPSR & _BV(SPIF))) ;
    *p = SPDR;
  }

... è una funzione di tipo void ... altro che, come da reference, ritornare quello che legge ... quello che legge lo mette al posto di quello che si è inviato !!!
O meglio, il reference è vero se si usa la transfer() passando come parametro SOLO un valore, ma NON se si passa un puntatore ed una lunghezza!!!

Tocca salvarsi quello che si invia perché lo altera!!! :crazy_face:

Lo metterò nel readme della libreria. :confused:

Guglielmo

1 Like

Con riferimento al tuo punto 4, ti confermo che, per come funziona la SPI.transfer() nel caso di buffer e lunghezza (metodo usato dal template della libreria), occorre necessariamente salvare il valore prima della put() o lo si altera ...

  Serial.print( "b=" );       // scrittura da 0 a x per 0x60 a 0x80
  j = 0;
  b = j;
  for (i = 0x0060; i <= 0x0080; i++) {
    Serial.print(b); Serial.print( ',');
    myNVSRAM.put ( i, b );
    j++;
    b = j;
  }

... una bella rottura di scatole, ma ... così è ... :roll_eyes:

Guglielmo

@nid69ita: mi fai una cortesia ... ti allego la nuova versione (1.0.1) della libreria che dovrebbe girare su MCU anche diverse da AVR ... fai un po' di prove e mi fai sapere?
Grazie :hugs:

NVSRAM.zip (90.0 KB)

Guglielmo

P.S.: Ho aggiornato anche il readme :wink: