problemi con PROGMEM

PROGMEM sposta il contenuto di una variabile dichiarata come costante nella flash, cio mi sarebbe utile per spostare un array da 2kB in flash, piuttosto che saturare completamente la ram.

l'array in questione lo trovate qui
è una serie di font riciclata per una matrice di led.

io ho trovato questa discussione sempre su PROGMEM

il problema è che non capisco questa stringa:

char* getString(const char* str) { strcpy_P(stringBuffer, (char*)str);return stringBuffer; }

che credo serva a far diventare la locazione di memoria della ram, al suo contenuto(cioe la locazione di memoria della flash dove viene salvato il dato), che a sua volta viene convertito nel dato stesso

prima di tutto il * cosa fa? so che è un puntatore, ma il reference non dice nulla d'altro, come ad esempio a cosa serva.

perche le parentesi graffe?

le funzioni che finiscono con _P sono incluse in avrdude come ad esempio PROGMEM stesso?

boschi:
perche le parentesi graffe?

E' una dichiarazione di funzione, se la scrivo così (su più righe) la riconosci ?

char* getString(const char* str) 
{ strcpy_P(stringBuffer, (char*)str);
  return stringBuffer; 
}

Il puntatore punta, appunto, ad un indirizzo di memoria. In questo caso si usa quella funzione per far caricare in un buffer che vive in ram il puntstore al dato che ti interrssa e cge fisicamente hai messo in flash.

Strcopy_P è una funzione della LibC che lavora con progmem. Tutte le funzioni che finiscono in _P riguardano appunto operazioni in flash.

Sul link che hai postato c'è Mauro cbe spiega ulteriormente la cosa

tra una bestemmia e l'altra ne sto lentamente venendo fuori.

quindi * trasforma una variabile nel suo indirizzo di memoria, mentre & trasforma un indirizzo nel suo contenuto

se non sbaglio la soluzione ai mie problemi potrebbe essere strcpy_P, una funzione che copia dalla flash a una variabile.

io ho messo strcpy_P(variabile da riempire con il contenuto della flash, array contenuto in flash)

il problema è che compilando mi dice "invalid conversion from 'char' to 'char*' [-fpermissive]"

noto che sia nel codice nel reference che in quello linkato da me prima dell array in flash mettono (char*)

cosa significa?

comunque anche con quello davanti mi da lo stesso errore :cry:

boschi:
quindi * trasforma una variabile nel suo indirizzo di memoria, mentre & trasforma un indirizzo nel suo contenuto

Hai capito esattamente il contrario :grinning:. Occhio che per gli array non è necessario prendere il loro indirizzo, nel senso che il "nome" di un array è già un puntatore (se non specifichi un indice).

Per l'altro errore posta esattamente quel che hai scritto, la linea di strcpy_P() e la dichiarazione delle variabili che le passi.

#include <avr/pgmspace.h>

#define LATCH_PIN 8       // Pin connected to ST_CP of 74HC595
#define CLOCK_PIN 12      // Pin connected to SH_CP of 74HC595
#define DATA_PIN  11      // Pin connected to DS of 74HC595

const byte FF[] PROGMEM = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};


void setup()
{
  // Set pins to output so you can control the shift register
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);
}

void loop()
{
  byte val = 0x01;
  for(byte x = 0; x < 8; x++)
  {
    char fontBuff;
    strcpy_P(fontBuff,FF[x]);
    digitalWrite(LATCH_PIN, LOW);
    shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, val);
    shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, ~fontBuff); 
    digitalWrite(LATCH_PIN, HIGH);
    val <<= 1;
    delay(100);
  }
}

il codice è questo.

serve a comandare una matrice di led con due 74hc595

il codice funzionava lasciando l'array in ram e modificando leggermente il secondo shiftout.

il ~ lo uso perche il secondo shift register comanda le masse dei led, quindi devo invertire i valori logici

la riga incriminata è la seconda del ciclo for

Un char contiene un carattere solo, strcpy (nelle varie varianti) copia stringhe.

Nel tuo caso non si parla di stringhe, visto che dovrebbero essere array di char terminati da '\0' (così almeno è come se li aspetta strcpy()), ma forse nemmeno singoli byte/char. Forse quel che ti serve sono array di byte di una certa dimensione? In tal caso devi predisporre fontBuff in modo che abbia la dimensione corretta, quindi riempirlo con una memcpy_P(), sempre che esista. Se non esiste dovrai ciclare con una pgm_read_byte(), se ricordo bene.

... esiste un bel documento da studiare relativo alla PROGMEM, lo metto in allegato a questo post :wink:

Guglielmo

Progmem.pdf (182 KB)

grazie mille Guglielmo!

spulciando quel pdf credevo di aver trovato la risposta ai miei problemi, poi ho compilato :sob:

come diceva SukkoPera il comando da usare (se non ho capito male) è pgm_read_byte, come si evince dalla pagina 5 di quel documento

all inizio non funzionava, poi ho capito che lui stava prendendo l'indirizzo della flash, quindi ho messo un & davanti alla variabile da leggere ed ha funzionato.

grazie millea tutti, mi siete stati davvero utilissimi, io non ci sarei mai arrivato da solo :slight_smile:

rieccomi, stavolta non riesco ad includere il file con i font completi.

il l'ho messo in una cartella font a sua volta nella cartella libraries di arduino

difatti riesco ad aggiungerla tramite il menu a tendina sketch -> includi, e mi aggiunge una stringa ad inizio codice che fa #include <font.h>

poi pero compilando mi dice che font non è stato dichiarato in questo ambito

Mettilo nella cartella dello sketch e cambia l'include in:

#include "font.h"

(Virgolette al posto di <>)

mi duole dirlo, ma non funziona.

prima di tutto relativo al file font.h dice :
"error: 'byte' does not name a type const byte font [256] [8] PROGMEM = {"

e per il codice stesso continua a dire che font non è stato dichiarato in questo ambito

Ma il file font.h l'hai fatto tu? Aprilo e aggiungi in cima:

#include <Arduino.h>

in realtà si :grinning:

bene e grazie a te funziona :smiley:

grazie ancora a tutti :smiley:

Potresti anche metterlo in eeprom invece che in flash,
Vantaggi :
Non lo riscrivi ad ogni upload inutilmente.
Gestisci il tutto con la libreria ufficiale arduino, più semplice di progmem

No, non mi piace tanto, e poi non riuscirei, l'array è da 2kB, l'eeprom invece solo 1

Allora sei obbligato,

Era un indicazione di ordine generale, magari altri che leggono hanno meno dati da gestire o schede con eeprom più grandi

Il problema è che con l'IDE di Arduino non puoi programmare la EEPROM insieme alla flash, quindi dovresti usare uno sketch solo per programmarla, quindi un altro per farci quel che vuoi. Fattibile, ma un po' scomodo insomma.

???

Esempio nel setup programmi la eeprom, dopo il primo upload commenti la parte di eeprom così non la ricarichi piu.
Nel caso devi modificare un font decommenti e modifichi la eeprom.

Lo sketch ti rimane uno, ed in un unico upload carichi sia eeprom che flash

Buona idea :).