PROGMEM herlaadbaar???? LedCube 4x4x4

Arduino specifieke Software
Berichten: 4
Geregistreerd: 08 Aug 2022, 21:38

PROGMEM herlaadbaar???? LedCube 4x4x4

Berichtdoor Earik » 09 Apr 2023, 18:22

Beste forumleden,

Ik ben al een tijdje bezig met een “ouderwetse 4x4x4 LedCube” goed lopend te krijgen. Dat gaat op zich ook wel, maar ik wil het wat verfijnen/uitbreiden.
Voor de mensen die niet bekend zijn met een 4x4x4 LedCube: dit is een kubus van 4 bij 4 bij 4 leds (5- of 3 mm), dus totaal 64 leds bestaande uit 4 lagen en 16 kolommen, die per led apart te besturen zijn of met meerdere tegelijk. De mogelijkheden van aansturen zijn dus legio (volgens mijn middelbare school wiskundige kennis 64! (faculteit)).

Ik gebruik het onderstaande programma, dat ik ooit van iemand heb gekregen en waarvoor ik hem nog steeds héél dankbaar ben.

Onder de hier staande ino-file staat het probleem beschreven dat ik tot op heden niet opgelost krijg.

Code: Alles selecteren
// LEDcube 4x4x4 //

#include <avr/pgmspace.h> // allows use of PROGMEM to store patterns in flash

#define CUBESIZE 4
#define PLANESIZE CUBESIZE*CUBESIZE
#define PLANETIME 3333 // time each plane is displayed in us -> 100 Hz refresh
#define TIMECONST 20   // multiplies DisplayTime to get ms - why not =100?

// LED Pattern Table in PROGMEM - last column is display time in 100ms units

boolean flipBits = false;

// row 4 bytes, col 4 bits per byte
// back bottom .. front

const unsigned char PROGMEM PatternTable[] = {
  B0000,B0000,B0000,B0000, B0000,B0000,B0000,B0000, B0000,B0000,B0000,B0000, B0000,B0000,B0000,B0000, 10,

//hier komen de rest van de "B0000, B0000, B0000, B0000, ………, x" files te staan (waarbij x > 0 ms)
//de hieronder staande regel geeft het einde van het programma aan, omdat de displaytime aan het einde van de regel 0 ms is

  // this is a dummy element for end of table (duration=0) aka !!!DO NOT TOUCH!!!
  B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, B0000, 0
};

/*
** Defining pins in array makes it easier to rearrange how cube is wired
** Adjust numbers here until LEDs flash in order - L to R, T to B
*/
const int C1 = 0;
const int C2 = 1;
const int C3 = 2;
const int C4 = 3;
const int C5 = 4;
const int C6 = 5;
const int C7 = 6;
const int C8 = 7;
const int C9 = 8;
const int C10 = 9;
const int C11 = 10;
const int C12 = 11;
const int C13 = 12;
const int C14 = 13;
const int C15 = A4;
const int C16 = A5;

const int L1 = A3;
const int L2 = A2;
const int L4 = A1;
const int L3 = A0;

int LEDPin[] = {C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15, C16};
int PlanePin[] = {L1, L2, L3, L4};

void layer_on(int layer) {
    digitalWrite(PlanePin[layer], HIGH);
}

void layer_off(int layer) {
    digitalWrite(PlanePin[layer], LOW);
}

void led_on(int led)  {
    digitalWrite(LEDPin[led], HIGH);
}

void led_off(int led) {
    digitalWrite(LEDPin[led], LOW);
}

void gled_on(unsigned char led) {
    digitalWrite(LEDPin[led & 0x0F], HIGH);
    digitalWrite(PlanePin[led >> 4], HIGH);
}

void gled_off(unsigned char led) {
    digitalWrite(LEDPin[led & 0x0F], LOW);
    digitalWrite(PlanePin[led >> 4], LOW);
}

void all_layers_off() {
    layer_off(0);
    layer_off(1);
    layer_off(2);
    layer_off(3);
}

void test(boolean ledforled, int n, int t) {
  int i,j, c;
  for (c = 0; c < n; c++) {
    all_layers_off();
    for (j = 0; j < 4; j++) {
      layer_on(j);
      for (i = 0; i < 16; i++) {
        led_on(i);
        delay(t-c);
        if (ledforled)
          led_off(i);
      }
      layer_off(j);
    }
  }
}

void buildTest() {
  int i,j;
    all_layers_off();
    for (j = 0; j < 4; j++) {
      layer_on(j);
      for (i = 0; i < 16; i++) {
        led_on(i);
      }
        delay(10000);
      layer_off(j);
      for (i = 0; i < 16; i++) {
        led_off(i);
      }
  }
}

void start() {
//  buildTest();
  test(true, 5, 5);
  test(false, 5, 5);
  test(true, 1, 30);
}

void tickle() {
    all_layers_off();
    layer_on(0);
    led_on(0);
    delay(2);
    led_off(0);
}

// initialization
void setup() {
    int pin; // loop counter
  // set up LED pins as output (active HIGH)
    for (pin=0; pin<PLANESIZE; pin++) {
      pinMode( LEDPin[pin], OUTPUT );
}
  // set up plane pins as outputs (active LOW)
    for (pin=0; pin<CUBESIZE; pin++) {
      pinMode( PlanePin[pin], OUTPUT );
  }
}

// display pattern in table until DisplayTime is zero (then repeat)
void loop() {
  // declare variables
    byte PatternBuf[PLANESIZE]; // saves current pattern from PatternTable
    int PatternIdx;
    byte DisplayTime; // time*100ms to display pattern
    unsigned long EndTime;
    int plane; // loop counter for cube refresh
    int patbufidx; // indexes which byte from pattern buffer
    int ledrow; // counts LEDs in refresh loop
    int ledcol; // counts LEDs in refresh loop
    int ledpin; // counts LEDs in refresh loop

// Initialize PatternIdx to beginning of pattern table
    PatternIdx = 0;
// loop over entries in pattern table - while DisplayTime>0

start();
  do {
    // read pattern from PROGMEM and save in array
    memcpy_P( PatternBuf, PatternTable+PatternIdx, PLANESIZE );
    PatternIdx += PLANESIZE;
                if (flipBits) {
                    byte* p = PatternBuf;
                    for (int i = 0; i < PLANESIZE; i++) {
                       *p++ = ~*p;
                    }
                }
    // read DisplayTime from PROGMEM and increment index
    DisplayTime = pgm_read_byte_near( PatternTable + PatternIdx++ );
    // compute EndTime from current time (ms) and DisplayTime
    EndTime = millis() + ((unsigned long) DisplayTime) * TIMECONST;
   
    // loop while DisplayTime>0 and current time < EndTime
    while ( millis() < EndTime ) {
      patbufidx = 0; // reset index counter to beginning of buffer
      // loop over planes
      for (plane=0; plane<CUBESIZE; plane++) {
   
        // load current plane pattern data into ports
        ledpin = 0;
        for (ledrow=0; ledrow<CUBESIZE; ledrow++) {
          for (ledcol=0; ledcol<CUBESIZE; ledcol++) {
            digitalWrite( LEDPin[ledpin++], PatternBuf[patbufidx] & (1 << ledcol) );
          }
          patbufidx++;
        }
     
                      // turn current plane on
//          digitalWrite( PlanePin[plane], LOW );
                             layer_on(plane);
          // delay PLANETIME us
          delayMicroseconds( PLANETIME );
                            layer_off(plane);
      } // for plane
    } // while <EndTime
  } while (DisplayTime > 0); // read patterns until time=0 which signals end
}


Het probleem:
Op een gegeven moment wordt PROGMEM dus geladen (vergeef me mijn mogelijke niet c++/arduino taalgebruik) met (per regel in het programma) 4 maal 4 groepen (4 lagen van de kubus) en binnen die 4 groepen is aan te geven welke kolommen er mee doen (16 kolommen (4 maal 4)).

De eerste regel van PROGMEM wordt bijvoorbeeld geladen met:
B0000,B0000,B0000,B0000, B0000,B0000,B0000,B0000, B0000,B0000,B0000,B0000, B0000,B0000,B0000,B0000, 10,

In dit geval 16 maal B0000 gescheiden door een komma. Dat betekent dat alle leds uit zijn gedurende 10 ms.

Een tweede regel in PROGMEM zou kunnen zijn:
B0001,B0000,B0000,B0000, B0001,B0000,B0000,B0000, B0001,B0000,B0000,B0000, B0001,B0000,B0000,B0000, 20,
In dit geval licht van elke laag de led in de eerste kolom op en de andere leds zijn uit (gedurende 20 ms).

Een derde voorbeeld:
B1111,B0000,B0000,B0000, B1111,B0000,B0000,B0000, B1111,B0000,B0000,B0000, B1111,B0000,B0000,B0000, 30,
In dit geval dus in elke laag de kolommen 1 t/m 4 aan en de andere leds blijven uit (gedurende 30 ms).

Per regel kost dit (vreemd genoeg) 18 óf 16 bytes.

Nu heb ik een Word-bestand van 56(!) pagina’s (wie het wil kan ik het sturen) met deze codes door flink het internet af te zoeken en zelf te programmeren (geeft mooie effecten).
Per pagina zijn er gemiddeld 67 regels met deze codes. Dit houdt per Word-pagina in dat ik dan ongeveer 67 maal 17 (18+16 gedeeld door 2) = 1139 bytes gebruik. Bij 56 pagina’s is dat 56 maal 1139 = 63784 bytes.
Dit past, kwam ik later pas achter, niet in de PROGMEM.

Toen heb ik een Mega Pro Min 2560 gebruikt (in ieder geval genoeg ruimte voor het programma), maar ook daar is de PROGMEM maximaal 32kB (ik dacht dat dat 64kB zou zijn).

Op de een of andere manier zou ik PROGMEM dus een tweede of bij nog grotere databestanden meer dan 2 keer in moeten kunnen lezen.
En daar zit nu de crux van mijn probleem.

Ik heb al heel wat sites bezocht waar ik dacht mijn probleem te kunnen oplossen, maar die heb ik nog steeds niet gevonden.
Het lijkt erop alsof ik meerdere strings moet aan gaan geven, maar mijn c++ kennis schiet daarbij flink te kort.

Het hieronder staande script heb ik via de site van Arduino (arduino.cc) gevonden en ik denk dat dat richting de oplossing van het probleem zou kunnen gaan, maar ik weet niet hoe ik dat in mijn eigen ino-file zou moeten opnemen.

Code: Alles selecteren
#include <avr/pgmspace.h>
const char set_0_string_0[] PROGMEM = "Set 0 String 0";   
const char set_0_string_1[] PROGMEM = "Set 0 String 1";
const char set_0_string_2[] PROGMEM = "Set 0 String 2";
const char set_0_string_3[] PROGMEM = "Set 0 String 3";

const char set_1_string_0[] PROGMEM = "Set 1 String 0";   
const char set_1_string_1[] PROGMEM = "Set 1 String 1";
const char set_1_string_2[] PROGMEM = "Set 1 String 2";

const char* const set0[] PROGMEM = { set_0_string_0, set_0_string_1, set_0_string_2, set_0_string_3 };
const char* const set1[] PROGMEM = { set_1_string_0, set_1_string_1, set_1_string_2 };

PGM_VOID_P const all_sets[2] = { set0, set1 };

char buffer[32];   

void setup() {
  Serial.begin(9600);
  while(!Serial);
  Serial.println("OK");
}

void loop() {
  for (int i = 0; i < sizeof(set0) / sizeof(set0[0]); i++) {
    strcpy_P(buffer, (char*)pgm_read_word(&(set0[i])));
    Serial.println(buffer);
    delay( 500 );
  }
}


Ik hoopt dat iemand mij hiermee (op weg) kan helpen.

Vriendelijke groet,
Earik

Advertisement

Berichten: 4067
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: PROGMEM herlaadbaar???? LedCube 4x4x4

Berichtdoor shooter » 16 Apr 2023, 18:13

Ik zou een memory stickje gebruiken en dan telkens 1 stukje ervan gebruiken of zelfs direct van het stickje naar de patternbuf want 64! is heel erg veel. en je kunt ook per laag een toestand zetten en dan verschuiven zodat je maar 16! plek nodig hebt, maar een directe oplossing heb ik niet
als je jouw beelden wilt opsturen dan graag naar shooter@home.nl
paul deelen
shooter@home.nl

Berichten: 68
Geregistreerd: 21 Apr 2013, 22:48
Woonplaats: Hoorn

Re: PROGMEM herlaadbaar???? LedCube 4x4x4

Berichtdoor babbelkwebbel » 17 Apr 2023, 07:23

misschien een EEprom op de I2C bus, en als het snel moet een Flash memory module op de SPI bus?

Berichten: 80
Geregistreerd: 02 Nov 2022, 13:03

Re: PROGMEM herlaadbaar???? LedCube 4x4x4

Berichtdoor ThHe » 18 Apr 2023, 00:36

PROGMEM wordt geladen met char maar slecht 4 bits worden gebruikt.
Daarom wordt de helf van PROGMEM niet optimaal gebruikt. (char = 8 bits)

Berichten: 80
Geregistreerd: 02 Nov 2022, 13:03

Re: PROGMEM herlaadbaar???? LedCube 4x4x4

Berichtdoor ThHe » 18 Apr 2023, 21:11

Hierbij dan ook de oplossing hoe PROGMEM beter gebruikt kan worden.

Aan de define wordt READSIZE toegevoegd.

Code: Alles selecteren
#define CUBESIZE 4
#define PLANESIZE CUBESIZE*CUBESIZE
#define READSIZE PLANESIZE /2

..........

De invulling van PROGMEM wordt gewijzigd.

oorspronkelijke invulling
Code: Alles selecteren
/*
const unsigned char PROGMEM PatternTable[] = {
  B0000,B0000,B0000,B0000, B0000,B0000,B0000,B0000, B0000,B0000,B0000,B0000, B0000,B0000,B0000,B0000, 10,
  B0001,B0000,B0000,B0000, B0001,B0000,B0000,B0000, B0001,B0000,B0000,B0000, B0001,B0000,B0000,B0000, 20,
  B1111,B0000,B0000,B0000, B1111,B0000,B0000,B0000, B1111,B0000,B0000,B0000, B1111,B0000,B0000,B0000, 30,
  B1011,B1010,B1001,B1110, B0101,B1001,B1110,B1001, B1111,B1010,B1001,B1110, B0101,B1001,B1110,B1001, 10,
  B0000,B0000,B0000,B0000, B0000,B0000,B0000,B0000, B0000,B0000,B0000,B0000, B0000,B0000,B0000,B0000, 0
};
*/


// De nieuwe invulling waarbij de unsigned char volledig gebruikt wordt.
Code: Alles selecteren
const unsigned char PROGMEM PatternTable[] = {
  B00000000,B00000000, B00000000,B00000000, B00000000,B00000000, B00000000,B00000000, 10,
  B00010000,B00000000, B00010000,B00000000, B00010000,B00000000, B00010000,B00000000, 20,
  B11110000,B00000000, B11110000,B00000000, B11110000,B00000000, B11110000,B00000000, 30,
  B10111010,B10011110, B01011001,B11101001, B11111010,B10011110, B01011001,B11101001, 10,
  B00000000,B00000000, B00000000,B00000000, B00000000,B00000000, B00000000,B00000000, 0
};


........ Uitbreiding bij het lezen van het pattern.

Code: Alles selecteren
   
    // read pattern from PROGMEM and save in array
    memcpy_P( PatternBuf, PatternTable+PatternIdx, READSIZE ); // READSIZE ipv PLANESIZE
    PatternIdx += READSIZE;                                    //
    for (int i=0; i < READSIZE; i++)                           // Pattern invullen door de bytes te splitsen
    {
   PatternBuf[READSIZE*2 - i*2 - 1] = PatternBuf[READSIZE -i -1] & 0xF;
        PatternBuf[READSIZE*2 - i*2 - 2] = PatternBuf[READSIZE -i -1] >> 4;
    }
   // rest van het programma
   if (flipBits) { ............
 

Berichten: 4
Geregistreerd: 08 Aug 2022, 21:38

Re: PROGMEM herlaadbaar???? LedCube 4x4x4

Berichtdoor Earik » 19 Apr 2023, 14:01

door shooter » 16 Apr 2023, 18:13
Ik zou een memory stickje gebruiken en dan telkens 1 stukje ervan gebruiken of zelfs direct van het stickje naar de patternbuf want 64! is heel erg veel. en je kunt ook per laag een toestand zetten en dan verschuiven zodat je maar 16! plek nodig hebt, maar een directe oplossing heb ik niet


Hallo Paul, dank voor je snelle reactie; daar had ik in ieder geval zeker nog niet aan gedacht.
Ik heb meerdere oplossingen aangedragen gekregen; ik kan in ieder geval weer verder. Bedankt en ik zal de files sturen.

Berichten: 4
Geregistreerd: 08 Aug 2022, 21:38

Re: PROGMEM herlaadbaar???? LedCube 4x4x4

Berichtdoor Earik » 19 Apr 2023, 14:06

door babbelkwebbel » 17 Apr 2023, 07:23
misschien een EEprom op de I2C bus, en als het snel moet een Flash memory module op de SPI bus?


Hallo Babbelkwebbel, ook bedankt voor je oplossing; ik ben me aan het oriënteren op de Flash Memory Module op de SPI bus.
Voor mij klinkt dat nu nog abracadabra, maar met wat zoekwerk kom ik er wel achter :) Bedankt!

Berichten: 4
Geregistreerd: 08 Aug 2022, 21:38

Re: PROGMEM herlaadbaar???? LedCube 4x4x4

Berichtdoor Earik » 19 Apr 2023, 14:08

door ThHe » 18 Apr 2023, 00:36
PROGMEM wordt geladen met char maar slecht 4 bits worden gebruikt.
Daarom wordt de helf van PROGMEM niet optimaal gebruikt. (char = 8 bits)


Hallo ThHe, dit zit er professioneel uit en ik ga dat zeker proberen; dank!!!
Dank voor het uitgebreide antwoord!!!

Terug naar Arduino software

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 12 gasten