Speicherprobleme bei Stringoperationen zusammen mit dem Ethernetshield (gelöst)

Dies ist die Fortsetzung des Threads:

Muss ich den SPI-Bus für die RFID-Karte selber steuern? (Modifiziert)
http://arduino.cc/forum/index.php/topic,117394.0.html

Was bisher geschah: :slight_smile:
Der Thread hat sich inzwischen so weit vom ursprünglichen Thema entfernt, dass ich mich entschlossen habe , einen Thread zu öffnen, dessen Thema der augenblicklichen Diskussion am nächsten kommt.

Also weiter geht's!

@pylon

Der Code für Deine Anwendung könnte dann so lauten:

char strbuf[92];

strnprintf(strbuf, 92, "GET /status?p0=playlist&p1=play&p2=%d-%d-%d-%d-%d&player=00:15:af:b8:ac:25 HTTP/1.1", serNum[0], serNum[1], serNum[2], serNum[3], serNum[4]);

Dazu habe ich drei Fragen:

  • Gehört der Befehl zum normalen Arduino-Wortschatz (1.0.1), oder benötige ich eine andere IDE?
  • Den Befehl "strnprintf()" kann ich nicht zuordnen. Wohin schreibt der Befehl?
  • Die Inhalte in der Klammer sind klar. Ich muss aber diesen Inhalt mit Client.print (...) an den Server übergeben. Den Übergang bekomme ich nicht hin. Wie würde denn der Code denn weiter aussehen?

Eberhard

Die Funktion sprintf() schreibt das Ergebnis als C-String (mit =-Terminierung) in den übergebenen Puffer. In Deinem Fall in das char-Array "strbuf" das vorher mit 92 Bytes deklariert wird.
Danach kannst Du einefach die Variable "strbuf" als String verwenden und z.B. mittels "client.println(strbuf);" an den Client ausgeben.

strnprintf ist nicht so leicht zu googlen, aber

snprintf (char* target, int size, const char* format, ... )

hat gegenüber dem klassischen sprintf den Vorteil, dass die Funktion nicht ausserhalb des erlaubten Bereichs schreibt.

Ist das jetzt ein Schreibfehler, oder gibt es wirklich noch snprintf(...)? Ich werd' wahnsinnig.

Wie würde meine Zeile denn dann lauten?

snprintf(strbuf, 92, "GET /status?p0=playlist&p1=play&p2=%d-%d-%d-%d-%d&player=00:15:af:b8:ac:25 HTTP/1.1", serNum[0], serNum[1], serNum[2], serNum[3], serNum[4]);

Bedeutet zulässiger Bereich bis strbuf[92] voll ist. Dann könnte man ja eigentlich auf die Null-Terminierung verzichten ?????

Eberhard

Dann könnte man ja eigentlich auf die Null-Terminierung verzichten.

Wenn snprintf das tut, ist der erzeugte string ohne 0 am Ende "nicht zu gebrauchen" ( jedenfalls nicht mit client.println(strbuf); )
print vertraut darauf, dass rechtzeitig die 0 kommt.

Müsste man reference doc lesen, probieren, und hätte dann das Problem, was der arme kleine Arduino denn nun in so einem Fall machen soll.

Tja, was soll ich sagen? Mit der verwendung von snprintf(...) und der Abkehr von String-Objekten, wird offensichtlich der Speicher vernünftig genutzt. Fakt ist: Alles läuft in diesem Stadium wie gewollt.

Allen, die mit viel Geduld mir gehölfen haben meinen herzlichsten Dank.

Ziel war es mit RFID-Karten den Logitech Media Server LMS zu steuern. Für Alle, die nach mir das gleiche Ansinnen haben, hier die entsprechenden Codeschnipsel. Der Sketch ist nicht komplett dargestellt, sondern enthält nur die Teile veränderte Definitionen, void setup(), void loop, und der Ethernetclient void playPlaylist()

Originalcode
/*
 * Documentation: RFID.pde
 * Created: Dr.Leong (WWW.B2CQSHOP.COM)
 * Creation Date: 2011.09.19
 * Modified:
 * Modified:
 * Description: Mifarel find cards ? anti-collision ? election card ? to read and write interface
 */

// Ergänzungen in den Definitionen
const int chipSelectPin = 9;    // ChipSelect für RFID-Shield
const int chipSelectEth = 10;  // ChipSelect für Ethernet-Shield
const int chipSelectSD = 4;     // ChipSelect für SD-Slot auf Ethernet-Shield
const int NRSTPD = 5;            // Set digital pin 5, Not Reset and Power-down
uchar serNum[5];                  // 4-byte card serial number, 5 byte checksum byte
char SBox[92];                      // Enthält später die Anweisung für den Server
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
byte ip[]={192,168,2,xxx};
byte server[] = {192, 168, 2, xxx };
EthernetClient client;


void setup() {                
   Serial.begin(9600);   // RFID reader SOUT pin connected to Serial RX pin at 2400bps 
   delay(1000);
   Ethernet.begin(mac, ip);
   SPI.begin();
   pinMode(chipSelectSD,OUTPUT);
   pinMode(chipSelectPin,OUTPUT);             
   pinMode(chipSelectEth,OUTPUT);
   pinMode(NRSTPD,OUTPUT);                    
   digitalWrite(chipSelectSD,HIGH);
   digitalWrite(chipSelectPin, LOW);           
   digitalWrite(chipSelectEth,HIGH);
   digitalWrite(NRSTPD, HIGH);

  MFRC522_Init();  
}

void loop()
{
//Serial.println(F("loop"));
  	uchar i,tmp;
	uchar status;
        uchar str[MAX_LEN];
        uchar RC_size;
        uchar blockAddr;	// select the operating block address 0 to 63

        
  		// Look for the card, return the card type
		status = MFRC522_Request(PICC_REQIDL, str);	
		if (status == MI_OK)
		{
                  //Serial.print(F("Request ausgeführt"));

                }


		// Anti-collision, return the card serial number 4-byte
		status = MFRC522_Anticoll(str);
		memcpy(serNum,str,16);
                if (status == MI_OK)
		{
                [b]// Mit dem nachfolgend der Befehl, der den Logitech Media Server veranlasst die Playlist im Parameter p2 auf dem Player mit der angegebenen Mac-Adresse zu spielen[/b]   

                snprintf(SBox, 92, "GET /status?p0=playlist&p1=play&p2=%d-%d-%d-%d-%d&player=00:15:af:b8:ac:25 HTTP/1.1", serNum[0], serNum[1], serNum[2], serNum[3], serNum[4]);
                Serial.println(SBox);
                playPlaylist();
              

		// Election card, return the card capacity
		RC_size = MFRC522_SelectTag(serNum);
		if (RC_size != 0)
		{  }
                
                //Serial.println(" ");
		MFRC522_Halt();			// command card into hibernation            
          
}
}

/*
 * Function: playPlaylist
 * Description: The Playlist is sent to the Logitech Media center
 * Input parameters: Cardnumber of RFID-Card
 * Return value:
 */
void playPlaylist()
{
  client.connect(server,9002);
  Serial.println(F("connecting...")); 
  if (client.connected()) 
    {
      Serial.println(F("connected"));
      while (client.available()) 
        {
        char c = client.read();
        Serial.print(c);
        }
      Serial.println(SBox);
      client.println(SBox);    // Befehl an Squeezeplay 
      client.println();
      Serial.print(F("abgesetzt"));
     } 
  else 
     {
       Serial.println(F("connection failed"));
     }
  Serial.print(F("Serverdaten lesen"));
  if (!client.connected()) 
    {
       client.stop();
    } 

}

.
.
.
  // Hierhinter liegen noch die Subroutines des RFID-Shields

Gruß Eberhard