Arbeitsspeicher sparen

Hallo zusammen,

ich habe einen Arduino UNO und komme an die Grenze mit dem verfügbaren Arbeitsspeicher.

Ich verwende mehrmals folgende Routine (Beispiel): Werden die Strings im RAM abgelegt?

const char *toProducer(int val)
{
  switch(val){
    case 1: return "Panasonic";break;
    case 5: return "Toshiba";break;
    case 9: return "SanDisk";break;
    default: return "unknown";break;
  }
}

sprintf_P(txt, PSTR("\nMnfID:  %02X %s\n"), int(id), toProducer(id)); Serial.print(txt);

Verwendung von PSTR: Spart das RAM?

const char *toProducer(int val)
{
  switch(val){
    case 1: return PSTR("Panasonic");break;
    case 5: return PSTR("Toshiba");break;
    case 9: return PSTR("SanDisk");break;
    default: return PSTR("unknown");break;
  }
}

Ist es besser die PSTR zu verwenden um Speicher zu sparen?
Und wie greife ich nun auf den PSTR dann zu?

Danke!!

Erstmal ist es besser, auf das switch zu verzichten und Arrays zu verwenden.
Dann bitte mit linearem Index
progmem doku

Und das ist mein Problem. Der Index ist nicht linear sondern willkürlich.

Wäre ein 2D-Array eine alternative?

1, "Panasonic"
5, "Toshiba"
9, "SanDisk"

Wie müsste ein Array aus Integer und String aufgebaut sein?

Gibt es einen logischen Grund für die willkürlichen Werte?

Gruß Tommy

Tommy56:
Gibt es einen logischen Grund für die willkürlichen Werte?

Producer-ID von SD-Karten.

Mein Vorschlag:

Eine Funktion, die über eine Entscheidungsstruktur (case oder if) aus der willkürlichen Nummer einen linearen Index macht, über den man aufs Array zugreifen kann.

Gruß Tommy

Tommy56:
über den man aufs Array zugreifen kann.

War auch mein Gedanke.

@TO:
Array [1, 5, 9] - Index finden.
Index auf Array ["hersteller1", "hersteller2", "hersteller3"] anwenden.

Index im Array finden ist eine Schleifensuche, eine Entscheidungsstruktur ist evtl. schneller, wenn es nicht zu viele sind. Bei 3 wird es wohl ein Nullsummenspiel werden.

Gruß Tommy

Tommy56:
Bei 3 wird es wohl ein Nullsummenspiel werden.

Da es tatsächlich viel mehr gibt, wird das hier nur raten.
Ich warte mal ab, was der TO noch bringt.

aloisus:
Wäre ein 2D-Array eine alternative?

1, "Panasonic"
5, "Toshiba"
9, "SanDisk"

Wie müsste ein Array aus Integer und String aufgebaut sein?

2D-Arrays sind im Forum meistens eine Structur - selten wirklich 2D.

Mach dir ein struct.
Mach daraus ein Array
Lass es im PROGMEM.
Lies den verlinkten Artikelk zu PROGMEM wie du auf die Daten zugreifst.
Übe eventuell mit einem einfachen Array.

struct SDcard
{
  byte id;  // gibt es IRGENDEINEN Grund für ein int? schon mal ne negative id gesehen?
  char name[];
};

const SDcard sdcard[] PROGMEM = {
  {1, "Panasonic"},
  {5, "Toshiba"},
  {9, "SanDisk"}
};

wie viele werden es? bei 3 würde ich den switch case lassen.

char name;

Kann das so funktionieren?
Meines Wissens nach benötigt dieses Konstrukt ein malloc() o.ä. und ist damit für das Flash aus dem Rennen.

bei 3 würde ich den switch case lassen.

Vielleicht ist ja sowas genau das richtige:

#include <Wire.h>
//#include <LCD.h>

size_t printProducer(Print &p, byte val)
{
  size_t len{0};
  switch(val){
    case  1: len += p.print(F("Panasonic")); break;
    case  5: len += p.print(F("Toshiba"));   break;
    case  9: len += p.print(F("SanDisk"));   break;
    default: len += p.print(F("unknown"));  
  }
  return len;
}



void setup() 
{ 
  Wire.begin();
  Serial.begin(9600);

   printProducer(Serial,1);
   
   Wire.beginTransmission(42);
   printProducer(Wire,9);
   Wire.endTransmission();


 //  printProducer(lcd,42);
}

void loop() 
{

}

schaffe es momentan nur mit einer festen char Größe.
Und der Umweg über strcpy_P gefällt auch nicht.
Trotzem, es kompiliert und gibt was aus.
Aber da sich der TO eh nicht beteiligt ist es eh wurst.

struct SDcard
{
  byte mid; // manufacturer ID
  char name[20];
};

const byte UNKNOWN = 255;

const SDcard sdcard[] PROGMEM = {
  {1, "Panasonic"},
  {5, "Toshiba"},
  {9, "SanDisk"},
  {UNKNOWN, "unknown"}
};

byte findMid(const byte needle)  // returns Index
{
  size_t len = sizeof(sdcard) / sizeof(sdcard[0]);
  for (size_t i = 0; i < len; i++)
  {
    byte actual = pgm_read_dword_near(&sdcard[i].mid);
    if (actual == needle) return i;
  }
  return len - 1;
}


void setup() {
  Serial.begin(115200);
  char buffer[20];
  strcpy_P(buffer, sdcard[findMid(1)].name);
  Serial.println(buffer);
}

void loop() {
}

Ja, einen Puffer im RAM brauchst Du schon, ob es Dir gefällt oder nicht oder die Variante mit dem F-Macro im Print.

Gruß Tommy

Noch so eine Variante, des geichen Spielchens…

//#include <Wire.h>
//#include <LCD.h>


const __FlashStringHelper *producer(const byte val) 
{
  switch(val)
  {
    case  1: return F("Panasonic") ; break;
    case  5: return F("Toshiba")   ; break;
    case  9: return F("ScanDisk")  ; break;
    default: return F("unknown")   ; break;
  }  
}





void setup() 
{ 
//  Wire.begin();
  Serial.begin(9600);

  Serial.println(producer(1));
  Serial.println(producer(3));
  Serial.println(producer(5));
  
//  Wire.beginTransmission(42);
//  Wire.print(producer(9));
//  Wire.endTransmission();
  
 //  lcd.print(producer(42));
}

void loop() 
{

}

Hallo Zusammen,

Danke für eure Beispiele.

@combie: Mir gefällt insbesondere dein Ansatz:

const __FlashStringHelper *producer(const byte val)
{
  switch(val)
  {
    case  1: return F("Panasonic") ; break;
    case  5: return F("Toshiba")   ; break;
    case  9: return F("ScanDisk")  ; break;
    default: return F("unknown")   ; break;
  } 
}

char txt[40];

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

  // die folgenden Zeilen funktionieren
  Serial.println(producer(1));
  Serial.println(producer(5));
  Serial.println(producer(9));

  // diese Zeilen funktionieren nicht (sind unvollständig)
  sprintf_P(txt, PSTR("Producer: 0x%02X %s"), 1, producer(1)); Serial.println(txt);
  sprintf_P(txt, PSTR("Producer: 0x%02X %s"), 5, producer(5)); Serial.println(txt);
  sprintf_P(txt, PSTR("Producer: 0x%02X %s"), 9, producer(9)); Serial.println(txt);
}

void loop()
{

}

Warum wird der String nicht vollständig ausgegeben wenn ich die sprintf Funktion verwende?

Weil es kein PSTR ist, sondern ein Zeiger auf eine __FlashStringHelper Instanz
(denke ich mal)

Weil es kein PSTR ist, sondern ein Zeiger auf eine __FlashStringHelper Instanz
(denke ich mal)

Das war nicht ganz richtig.

Und dennoch: So schwer ist das nicht....

// diese Zeilen funktionieren perfekt
sprintf_P(txt, PSTR("Producer: 0x%02X %S"), 1, producer(1)); Serial.println(txt);
sprintf_P(txt, PSTR("Producer: 0x%02X %S"), 5, producer(5)); Serial.println(txt);
sprintf_P(txt, PSTR("Producer: 0x%02X %S"), 9, producer(9)); Serial.println(txt);