Colocar buffer en char

Buenas, estoy realizando un código para leer datos provenientes de RFID mediante el módulo RC522. El caso es que para trabajar con él, uso un byte buffer[18] y recorro el bloque que quiero leer del modulo y lo introduzco dentro del buffer. Obviamente esto funciona y consigo guardar la cadena de caracteres dentro del buffer, el problema ocurre cuando quiero enviar ese buffer a Thingsboard, necesito una cadena de caracteres tipo char, por lo que intento usar: cadena = (char*)buffer;.
Si realizo esto, funciona pero me incorpora unos caracteres al final del char que no quiero, hay alguna forma de realizar esta conversión?

Lee las normas y postea tu còdigo adecuadamente.
Hablar de que has hecho se potencia con el código de otro modo solo imaginaremos cosas y no podremos darte buenos consejos.

Perdón, coloco el código:

// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent())
return;

// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial())
return;

byte sector = 1;
byte blockAddr = 5; //Se especifica que bloque se leera _____------______-----______
byte dataBlock[] = {
0x01, 0x02, 0x03, 0x04, // 1, 2, 3, 4,
0x05, 0x06, 0x07, 0x08, // 5, 6, 7, 8,
0x08, 0x09, 0xff, 0x0b, // 9, 10, 255, 12,
0x0c, 0x0d, 0x0e, 0x0f // 13, 14, 15, 16
};
byte trailerBlock =  sector * 4 + 3;
MFRC522::StatusCode status;
byte buffer[18];
byte size = sizeof(buffer);

Serial.println(F("Datos actuales en el sector:"));
mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
Serial.println();

// Read data from the block
Serial.print(F("Cargando dato del bloque ")); Serial.print(blockAddr);
Serial.println(F(" ..."));
status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Read() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
}
Serial.print(F("Dato en el bloque ")); Serial.print(blockAddr); Serial.println(F(":"));
dump_byte_array(buffer, 16); Serial.println();
nombre = (char*)buffer;
Serial.print(nombre);
/ envio de datos a Thingsboard
      //Se comprueba si esta conectado a la red wifi
      if (!tb.connected() ){
          reconnect();
      }
      Serial.println("Conectado con el broker");
      tb.sendTelemetryString("tipo", nombre);
Serial.println();
void dump_byte_array(byte *buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.write(buffer[i]);

}
}

El problema ocurre en:

nombre = (char*)buffer;

Ya que me guarda lo que hay dentro del buffer que es una fecha, supongamos 12/12/22 pero además al final se le añaden unos caracteres que no quiero como Ss.

Si debe ser un String entonces debes converter un char byte de 18 bytes a String.
Pero tuve que deducirlo porque no esta claro en tu código por no haber posteado TODO el código.

Este código funciona

// Incluimos la librería de control del sensor DHT11
#include "Arduino.h"

byte cString[18] = "012345678901234567";

void setup() {
  String aString;
  Serial.begin(115200);
  delay(2000);

  aString = cString;
  Serial.println(aString);
}

void loop() {
}

image

Copiando tu código, me aparece lo siguiente:

initializer-string for array of chars is too long [-fpermissive]

Te comento un poco mejor el problema, estoy trabajando con un módulo RFID que me aporta lo siguiente:


Entonces mediante un byte buffer recorro los bytes pertenecientes al bloque 60 por ejemplo, introduciendo todos lo que hay dentro de los bytes del 0 al 15 dentro del buffer (en hex si no me equivoco). Lo que yo necesito es pasar ese buffer a una cadena de caracteres tipo CHAR, no String, perdon por la confusión. Entonces declaro:

char * nombre;
void setup(){
}
void loop(){
byte buffer[18];
byte size = sizeof(buffer);
byte block=60;
//Ahora mediante la función 
status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(block, buffer, &size);
//Con esto ya he introducido dentro del buffer los bytes que contiene
//ahora intento pasarlo a un char
nombre = (char*)buffer;
//Esto funciona a medias, porque me crea una instancia a ese char pero me añade caracteres inexistentes dentro del bloque
}

No se si es que me añade, pero si compilo y muestro los datos me aparece esto


lo rojo es lo proveniente de nombre = (char*)buffer;, el Ss del final no deberia aparecer

Parece que no has entendido.

nombre debe ser String. Es es lo que requiere para enviar aquí

  tb.sendTelemetryString("tipo", nombre);

En el bloque 4 se ven cuatro espacios en blanco después de la palabra "pintura" (20 20 20 20).

Seguramente el bloque 3 tendrá los bytes 53 73 00, 53 73 20 00, 53 73 20 20 00 o algo así. Aquí estoy adivinando porque no se muestra el bloque 3.

Como quiera que sea se imprimirán todos los bytes (caracteres) a partir de la 'c' de 'cubo' hasta que se encuentre un byte con valor 00.

Para decidir si se imprimen caracteres inexistentes dentro del bloque necesitamos ver los bloques contiguos, como mínimo el contenido del bloque 3.

Si compartes tu programa y cuál es su propósito estaremos en mejores condiciones de ofrecer ayuda.

El código sería el siguiente:

#include <SPI.h>
#include <MFRC522.h>
#include <WiFiNINA.h>
#include <ThingsBoard.h>
#define TOKEN               "rskVgWtV1pUPqPE4bks0"
#define THINGSBOARD_SERVER  "demo.thingsboard.io" 
#define RST_PIN 6 // Configurable, see typical pin layout above
#define SS_PIN 7 // Configurable, see typical pin layout above
int status = WL_IDLE_STATUS;
//Credenciales para conexion WiFi
const char* ssid      = "vodafoneBA45";
const char* password  = "B84306182";
// Inicializamos el cliente y el objeto
WiFiClient mkr1010Client;
ThingsBoard tb(mkr1010Client);
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.

MFRC522::MIFARE_Key key;

char* nombre;
char* resultado;

//Función para conectar arduino a la red WiFi
void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while ( WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
setup_wifi();
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card

// using FFFFFFFFFFFFh which is the default at chip delivery from the factory
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF;
}

Serial.println(F("Ingrese Tarjeta"));
}

/**
* Main loop.
*/
void loop() {
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent())
return;

// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial())
return;
byte sector = 1;
byte blockAddr = 4; //Se especifica que bloque se leera _____------______-----______
byte dataBlock[] = {
0x01, 0x02, 0x03, 0x04, // 1, 2, 3, 4,
0x05, 0x06, 0x07, 0x08, // 5, 6, 7, 8,
0x08, 0x09, 0xff, 0x0b, // 9, 10, 255, 12,
0x0c, 0x0d, 0x0e, 0x0f // 13, 14, 15, 16
};
byte trailerBlock =  sector * 4 + 3;
MFRC522::StatusCode status;
byte buffer[18];
byte size = sizeof(buffer);

Serial.println(F("Datos actuales en el sector:"));
mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
Serial.println();

// Read data from the block
Serial.print(F("Cargando dato del bloque ")); Serial.print(blockAddr);
Serial.println(F(" ..."));
status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Read() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
}
Serial.print(F("Dato en el bloque ")); Serial.print(blockAddr); Serial.println(F(":"));
dump_byte_array(buffer, 16); Serial.println();
nombre = (char*)buffer;
Serial.println(nombre);
Serial.println(resultado);
Serial.println();

 // envio de datos a Thingsboard
      //Se comprueba si esta conectado a la red wifi
      if (!tb.connected() ){
          reconnect();
      }
      Serial.println("Conectado con el broker");
      tb.sendTelemetryString("tipo", nombre);
      tb.loop();
      delay(4000);
}

void dump_byte_array(byte *buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.write(buffer[i]);

}
}

void reconnect() {
  // Loop until we're reconnected
  while (!tb.connected()) {
    status = WiFi.status();
    if ( status != WL_CONNECTED) {
      WiFi.begin(ssid, password);
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("Connected to AP");
    }
    Serial.print("Connecting to ThingsBoard node ...");
    // Attempt to connect (clientId, username, password)
    if (tb.connect(THINGSBOARD_SERVER, TOKEN))  {
        Serial.println( "[DONE]" );
    } else {
        Serial.print( "[FAILED] [ rc = " );
        Serial.println( " : retrying in 5 seconds]" );
        delay( 500 );
    }
  }
}

Lo que quiero es obtener el dato proveniente del bloque en concreto en tipo char no byte, en este caso cubo pintura. Si lo que comentas es cierto, que busca hasta encontrar un byte con valor 00 lo que hago no me valdría, ya que yo solo quiero única y exclusivamente los 16 bytes correspondientes a un bloque, pero no encuentro la forma de hacer esta conversión del buffer a char.

¿Qué valor tendría resultado?

nombre = (char*)buffer; 
Serial.println(nombre); 
Serial.println(resultado);

Saludos

Lo rojo proviene de nombre, no de buffer

Puedes comprobarlo modificando

así:

Serial.print("buffer: [");
dump_byte_array(buffer, 16); Serial.println("]");

nombre = (char*)buffer;
Serial.print("nombre: [");
Serial.print(nombre);
Serial.println("]");

Lo que pasa aquí es que

dump_byte_array(buffer, 16);

escribe 16 caracteres de la memoria empezando con buffer[0] y

Serial.println(nombre)

escribe todo lo que hay en memoria a partir de buffer[0] hasta que encuentra un 0x00. Recuerda que buffer y nombre son apuntadores, así que

nombre = (char*)buffer;

hace que nombre apunte a buffer[0].



Para excluir los caracteres más allá del bloque y considerando que buffer tiene 18 bytes, puedes escribir una de estas instrucciones:

nombre[16] = 0x00;
nombre[16] = 0;
nombre[16] = '\0';

Este sketch ilustra algunos de estos conceptos:

// pruebas de equivalencia de char* y byte[]

char *nombre;
byte buffer[18];

void setup() {
  Serial.begin(115200);
  Serial.println("\nPruebas...");

  // cargar buffer
  for (int i = 0; i < 18; i++) {
    buffer[i] = 'A' + i;
  }
  // imprimir el contenido de buffer y un poco más, byte por byte
  dumpMem("Contenido INICIAL de buffer", buffer, 25);

  // ver el contenido inicial de nombre
  Serial.print("nombre0: ["); Serial.print(nombre); Serial.println("]");

  // igualar apuntadores
  nombre = (char*)buffer;
  Serial.print("nombre1: ["); Serial.print(nombre); Serial.println("]");

  // "recortar" nombre a 16 caracteres
  nombre[16] = '\0';
  Serial.print("nombre2: ["); Serial.print(nombre); Serial.println("]");

  // "recortar" nombre a 5 caracteres
  nombre[5] = '\0';
  Serial.print("nombre4: ["); Serial.print(nombre); Serial.println("]");

  // ver como quedó buffer
  dumpMem("Contenido FINAL de buffer", buffer, 25);
}

void loop () {
}

void dumpMem(String titulo, byte *inicio, unsigned int n) {
  Serial.println("Vaciado de memoria de " + titulo);
  Serial.println("\t#\tHEX\tASCII");
  for (unsigned int i = 0; i < n; i++ ) {
  	Serial.print("\t");
  	Serial.print(i);
  	Serial.print("\t");
  	if (inicio[i] < 0x10) {
  		Serial.print("0");
  	}
  	Serial.print(inicio[i],HEX);
  	Serial.print("\t'");
    Serial.write(inicio[i]);
  	Serial.println("'");
  }
  Serial.println();
}

O puedes reducir el tamaño del buffer de 18 a 16...

Resultado no tiene nada, eso fue una cosa que hice pero al final descarté y no he borrado del codigo.

Lo que dices lo he intentado varias veces, colocar un \0 en algún sitio del array pero no se porque cuando intento hacer algo de esto, a la hora de subir el código el IDE se queda "bugueado" y si consigue subirlo el arduino no funciona correctamente, teniendo que quemar el bootloader. No sé que puede estar ocurriendo. He minimizado el código lo máximo posible para ver si era fallo de librerías, si alomejor wifinina o alguna estaban impidiendo el funcionamiento pero no es así. El código que he intentado implementar para hacer la prueba es el siguiente:

#include <SPI.h>
#include <MFRC522.h>


#define RST_PIN 6 // Configurable, see typical pin layout above
#define SS_PIN 7 // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
MFRC522::MIFARE_Key key;

char* nombre;
byte buffer_1[18];
void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card

// using FFFFFFFFFFFFh which is the default at chip delivery from the factory
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF;
}

Serial.println(F("Ingrese Tarjeta"));
nombre[16]= 0x00;
}
void loop() {
// Look for new cards
Serial.print("Buscando...");
if ( ! mfrc522.PICC_IsNewCardPresent())
return;
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial())
return;
Serial.print("Encontrado");


byte sector = 1;
byte blockAddr = 4; //Se especifica que bloque se leera _____------______-----______
byte dataBlock[] = {
0x01, 0x02, 0x03, 0x04, // 1, 2, 3, 4,
0x05, 0x06, 0x07, 0x08, // 5, 6, 7, 8,
0x08, 0x09, 0xff, 0x0b, // 9, 10, 255, 12,
0x0c, 0x0d, 0x0e, 0x0f // 13, 14, 15, 16
};

byte trailerBlock =  sector * 4 + 3;
MFRC522::StatusCode status;
byte buffer_1[18];
byte size = sizeof(buffer_1);

Serial.println(F("Datos actuales en el sector:"));
mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
Serial.println();

// Read data from the block
Serial.print(F("Cargando dato del bloque ")); Serial.print(blockAddr);
Serial.println(F(" ..."));
status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer_1, &size);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Read() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
}
Serial.print(F("Dato en el bloque ")); Serial.print(blockAddr); Serial.println(F(":"));
dump_byte_array(buffer_1, 16); Serial.println();
nombre = (char*)buffer_1;
Serial.println(nombre);
Serial.println();
  // Detener el lector
  mfrc522.PICC_HaltA();
  // Detener la encriptación Crypto1
  mfrc522.PCD_StopCrypto1();
      delay(2000);

}
void dump_byte_array(byte *buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.write(buffer[i]);

}
}

No se que es lo que se está haciendo mal, ya que el código compila sin errores. Pero a la hora de correrlo se buguea todo, lo mismo estoy tocando algún registro que no debo o estoy realizando algo que produzca algún tipo de corrupción en el código, no lo sé.
El fallo o el error se encuentra en:

nombre[16]= 0x00;

Ya que si quito esto funciona correctamente (aportandome el Ss del final que no quiero), también he probado las otras opciones:

nombre[16] = 0;
nombre[16] = '\0';

y ocurre lo mismo, cuando corro el programa me indica que no se reconoce el dispositivo y tengo que quemarle el bootloader de nuevo. Con respecto a disminuir el buffer de 18 a 16 no me funciona tampoco, no se que pasa con esto.

Los 2 caracteres "de más", en tu ejemplo "Ss" son los 2 bytes del CRC.
El buffer no puede tener menos de 18 bytes, está así definido por la librería.
Si haces

nombre[16]= 0x00;

en setup(), no te va a dar resultado porque luego va a ser reescrito por

nombre = (char*)buffer_1;

Además nombre no tiene una longitud definida, no se si es válido acceder a una posición que todavía no existe.

Prueba hacerlo de este modo

buffer_1[16] = 0;
buffer_1[17] = 0;
nombre = (char*)buffer_1;

Saludos

Después de declarar

nombre apunta precisamente a la sección de memoria donde reside el bootloader, y al modificar nombre[16] estamos modificándolo (descomponiéndolo)

Esta instrucción:

debe ir después de

que es la que hace que nombre apunte a donde queremos. De esta forma:

nombre = (char*)buffer_1; // nombre apunta a buffer_1[0]
nombre[16]= 0x00; // nombre[16] apunta a buffer_1[16]

Entonces

Imprimirá un máximo de 16 caracteres antes de encontrar un fin de string (0x00)

Pero se supone que el bootloader está en flash, no se podría modificar con una asignación lisa y llana.
¿O me equivoco?

Saludos

Es correcto.


Posiblemente

nombre[16]= 0x00;

tiene algún efecto indeseado/impredecible cuando no se ha sido asignado aún un valor a nombre.

Gracias, se debía a esto. Supongo que la opción de gatul también sería valida.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.