How make a kind of scanf()?

Hello, I'm actually discovering Arduino Uno and how program it and I wanted to know how make a scanf() on Arduino?

In my project, I want to set a clock thanks to the serial monitor. For example, I display something like "Set hours" on the serial monitor, then the user write with the keyboard "11" and then the value is stored on a variable "hours". Same thing with minutes and seconds.

But I don't know how store 2 characters typed by user on only one variable. The function Serial.read() can only separate each characters you write. So I wanted to know if you can help me with that problem?

An other problem I had, was with the function Serial.read(), I tried the example written on Arduino website and I don't know why, I need to subtract 48 to my value to print the same character the user wrote.

int incomingByte = 0;

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

void loop() {

        if (Serial.available() > 0) {
                incomingByte = Serial.read();

                Serial.print("I received: ");
                Serial.println(incomingByte, DEC);      // In my case, I need to write that: Serial.println(incomingByte-48, DEC);
        }
}

Thanks :slight_smile:

While this is not the scanf() you want, it's pretty simple and I'm sure you can generalize it to your needs:

char incomingBytes[10];
int vals[6];

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

void loop() {
 
  if (Serial.available() > 0) {
    Serial.readBytesUntil('\n', incomingBytes, sizeof(incomingBytes) / sizeof(char) );
   vals[0] = atoi(incomingBytes);
    Serial.print("I received: ");
    Serial.println(vals[0], DEC);      // In my case, I need to write that: Serial.println(incomingByte-48, DEC);
  }
}

But I don't know how store 2 characters typed by user on only one variable.

What kind of variable? How do you know how many have been typed?

If the Arduino is prompting "Set hours", and the user is entering a value in the Serial Monitor, the Serial Monitor can append data to what the user types, such as CR and LF or CR only. Use one of these options. Then, read and store data that arrives on the serial port until the end-of-packet marker arrives.

char buff[8];
byte index = 0;
bool ended = false;

void loop()
{
   while(Serial.available() > 0)
   {
      if(index < 8)
      {
         char letter = Serial.read();
         if(letter != '\n' && letter != '\r')
         {
            buff[index++] = Serial.read();
            buff[index] = '\0';
         }
         else
         {
             ended = true;
         }
      }
   }

   if(ended)
   {
       // Use the data in buff
        index = 0;
        ended = false;
   }
}

Using the data in buff means, typically, calling atoi(buff) and storing the returned int somewhere. Where depends on what the prompt (not shown) was.

If I understand, with your code, I just need to declare a int variable,then this variable will be equals to atoi(buff)?

And normally, if the user write "123456", this variable will be equals to "123456"?

Because I tried it, I wanted to display this variable but there's nothing printed except "0"

An int on an Arduino is 2 bytes and won't hold a number as big as 123456, and atoi() will fail. If no conversion is performed, it returns 0, which is what you're seeing. However, it should return either INT_MAX or INT_MIN if overflow or underflow is detected.

Ok, thanks it works :slight_smile:

I will "study" that code because I never use atoi() and sizeof(). I know a little what is it but not enough about it.

How about sscanf?

The expression:

sizeof(incomingBytes) / sizeof(char)

is commonly used to determine how many elements are contained in an array. The first subexpression, sizeof(incomingBytes), uses the sizeof() operator to return the number of bytes the compiler allocated to incomingBytes. Since each char takes 1 byte and I defined 10 chars for the array, this subexpression returns 10. The second subexpression, sizeof(char), returns the number of bytes allocated for a char, or one byte for the Arduino. Therefore, 10 / 1 = 10 elements in the incomeingBytes[] array.

The advantage of this approach is twofold: 1) if you change the definition of the number of elements in the array, say from 10 to 20, the last argument in readBytesUntil() is automatically adjusted for you...you don't have to edit it and 2) if you would move this code to a platform where a char might take 2 bytes (e.g., Unicode), the sizeof() expressions automatically adjusts for the different data sizes.