Conversion of String to Char

I need to convert a String which I read from the SD card on Arduino.

This is how I read it :

String line= NewFile.readStringUntil('\n'); // The value copied to the line is "*IDN?"

*IDN? is my command which i want to execute.

I need this string to be used here,
scpi_execute_command is a library function as follows:

scpi_execute_command(struct scpi_parser_context* ctx, char* command_string, size_t length)

I am doing it this way :

 NewFile = SD.open("commands.txt");      // open or create file and overwrite existing file 
   if (NewFile) {   
   
   
     String line= NewFile.readStringUntil('\n');
     Serial.print("Line read from the sd card is :"); Serial.print(line);
  
     int llength = line.length();
     Serial.println(llength);
     char my_buffer[256];
     line.toCharArray(my_buffer,llength);
     
   if(llength > 0)
    {
      scpi_execute_command(&ctx, my_buffer,llength);                  // function call for execution of command
    }

}

The command does not execute. I dont know what is wrong

How to perform this conversion in Arduino?

I am doing it this way :

Which is obviously wrong. The second argument to toCharArray() is NOT the length of the String. The instance that you are calling toCharArray() on already knows THAT. RTFM!

The command does not execute.

And you know that how? Proof is FAR more useful than wild-assed assertions.

What IS in my_buffer after the call to toCharArray()? THAT would be useful information. Make CERTAIN that you can see EVERY character in the array.

I suspect, of course, that you have non-printable characters in the array (with the stupid name. Who else's buffer would it be?) and that they are the cause of the function not doing what you expect with the data you send it. Because it KNOWS you passed it rubbish.

Hello,

Well, I would have liked it more if the reply would be without any absurd comments ..(even about how i should name my array)

my_buffer prints *IDN

my_buffer prints *IDN

Prove that!

CODE:

NewFile = SD.open("commands.txt");      // open existing file 

   if (NewFile) {   
   
     String line= NewFile.readStringUntil('\n');                              //Read from the SD card
     Serial.print("Line read from the sd card is :"); Serial.print(line); Serial.println("");
     int llength = line.length();
     Serial.println(llength);
     char my_buffer[256];
     line.toCharArray(my_buffer,llength);
     Serial.print(" The value in my_buffer is :"); Serial.print(my_buffer);
     
   if(llength > 0)
    {
      scpi_execute_command(&ctx, my_buffer,llength);                  // function call for execution of command
    }

}

OUTPUT:

Initializing SD card...
initialization done.
Line read from the sd card is :*IDN?
5
 The value in my_buffer is :*IDN

Didn’t I mention that you needed to “Make CERTAIN that you can see EVERY character in the array.”?

Serial.print("The buffer contains: >")
Serial.print(my_buffer);
Serial.println("<");

Now, show us THAT output.

Line read from the sd card is :*IDN?
5
The value in my_buffer is :*IDN

Is the ‘?’ important ?

Initializing SD card...
initialization done.
Line read from the sd card is :*IDN?
5
The buffer contains: >*IDN<

Please explain how ‘*’, ‘I’, ‘D’, and ‘N’ is 5 characters.

Try this:

Serial.println("my_buffer:");
for(byte i=0; b<strlen(my_buffer); b++)
{
   Serial.print(b);
   Serial.print(") ");
   Serial.println(my_buffer[b], HEX);
}
Serial.println("=============");

I changed the command to :- :MEASURE.PRINT
It truncates the last character.
only prints :

Initializing SD card…
initialization done.
Line read from the sd card is ::MEASURE:PRINT
14
The buffer contains: >:MEASURE:PRIN<

JiaoJiao:
Is the '?' important ?

The '?' is still missing...

The second argument to toCharArray() is NOT the length of the String. The instance that you are calling toCharArray() on already knows THAT. RTFM!

Clearly, you haven't RTFM yet.

You are telling the the toCharArray() method that your array can hold 14 characters, when the String is 14 characters long. Since the array can only hold 14 characters, and one of them needs to be the NULL terminator, there is only room for the first 12 characters from the String. So, of course you lose the last one.

If you had read the stupid manual, you would KNOW that the second argument is supposed to be the size of the array, NOT the number of characters in the String.

I add a null character in the command and it prints all the characters in the buffer (i get the whole command now). Still it doesn't execute the command.

I add a null character in the command and it prints all the characters in the buffer (i get the whole command now).

That was NOT the correct solution.

Still it doesn’t execute the command.

Bummer. You still haven’t provided any proof of that.

That was NOT the correct solution.

OK.

Here you go:

Initializing SD card...
initialization done.
my_buffer:
:MEASURE:PRINT

This is the function from the library:

scpi_execute_command(struct scpi_parser_context* ctx, char* command_string, size_t length)

The whole code:

#include <scpiparser.h>
#include <Arduino.h>
#include <SPI.h>
#include "SdFat.h"
SdFat SD; 

struct scpi_parser_context ctx;

scpi_error_t identify(struct scpi_parser_context* context, struct scpi_token* command);
scpi_error_t print_value(struct scpi_parser_context* context, struct scpi_token* command);
scpi_error_t print1_value(struct scpi_parser_context* context, struct scpi_token* command);

File NewFile;



void setup()
{
  struct scpi_command* measure;
  struct scpi_command* value;


  /* First, initialise the parser. */
  scpi_init(&ctx);  

  /*
   * After initialising the parser, we set up the command tree.  Ours is
   *
   *    *IDN?         -> identify
   *  :MEASure
   *    :PRInt      -> print_value
   *  :VALue
   *    :PRInt1?    -> print1_value
   */
  scpi_register_command(ctx.command_tree, SCPI_CL_SAMELEVEL, "*IDN?", 5, "*IDN?", 5, identify);     //Initialise SameLevel function of Identify

  measure = scpi_register_command(ctx.command_tree, SCPI_CL_CHILD, "MEASURE", 7, "MEAS", 4, NULL);  // Command tree first child with main header name
  value = scpi_register_command(ctx.command_tree, SCPI_CL_CHILD, "VALUE", 5, "VAL", 3, NULL); 
  
  scpi_register_command(measure, SCPI_CL_CHILD, "PRINT", 5, "PRI", 3, print_value);            // Command tree subchild  to the first child

  scpi_register_command(value, SCPI_CL_CHILD, "PRINT1?", 7, "PRI1?", 5, print1_value);            // Command tree subchild  to the first child
  
   
   pinMode(15, OUTPUT); 


   Serial.begin(9600);
   Serial.println("Type any character to start");
  while (Serial.read() <= 0) {}
  Serial.print("Initializing SD card...");
  Serial.println();
 
  pinMode(SDCARD_SS_PIN, OUTPUT);
   
  if (!SD.begin(SDCARD_SS_PIN)) {
    Serial.println("initialization failed!");
    return;
  }
  
  Serial.println("initialization done.");

   
   NewFile = SD.open("commands.txt");      // open existing file 

   if (NewFile) {   
   
     String line= NewFile.readStringUntil('\n');                              //Read from the SD card
     Serial.print("Line read from the sd card is :"); Serial.print(line); Serial.println("");
     int llength = line.length();
     Serial.println(llength);
     char my_buffer[256];
     line.toCharArray(my_buffer,llength);
    Serial.println("my_buffer:");
    Serial.println(my_buffer);
    
/*for(int b=0; b < strlen(my_buffer); b++)
{
   Serial.print(b);
   Serial.print(") ");
   Serial.println(my_buffer[b]);
}
Serial.println("=============");*/
     
   if(llength > 0)
    {
      scpi_execute_command(&ctx, my_buffer,llength);                  // function call for execution of command
    }
    
}

}

void loop()
{
  
}


/*
 * Respond to *IDN?
 */
scpi_error_t identify(struct scpi_parser_context* context, struct scpi_token* command)
{
  scpi_free_tokens(command);                                      
  Serial.println("MKR ZERO");
  
  return SCPI_SUCCESS;                                                     
}


/*
 * Respond to the command :MEASURE:PRINT
 */
scpi_error_t print_value(struct scpi_parser_context* context, struct scpi_token* command)
{
  scpi_free_tokens(command);
  Serial.println("Level 1 reached");
  return SCPI_SUCCESS;
}

/*
 * Respond to the command :VALUE:PRINT1?
 */
scpi_error_t print1_value(struct scpi_parser_context* context, struct scpi_token* command)
{
  scpi_free_tokens(command);
  Serial.println("Level 2 reached");
  return SCPI_SUCCESS;
}

This is the function from the library:

That is the function SIGNATURE. Where is the function IMPLEMENTATION? There just might be a clue there. Or, you could post a link to the library.

And, post ALL of your code, not just snippets of output that you claim came from the code you didn't post.

I did post the whole code already.

link to the library: https://github.com/LachlanGunn/oic/tree/master/src/ArduinoSCPIParser

I did post the whole code already.

The output you posted wasn’t created by the code you posted.

You are STILL not calling toCharArray() correctly.

Fix that. or I’m done.

PaulS:
The output you posted wasn't created by the code you posted

+1

Added a null character to the command in the file stored in SD card.(I have added the .txt file on the sd card for you to see)

The code is the same only earlier print statement was commented out because you were interested in the value of buffer. BUT its the SAME code.

commands.txt (15 Bytes)