Serial to decimal from hex input

Hey, I am currently trying to get an serial input into my program and then use that string to get four independent char outputs that I can use to convert them to decimal.
So for better understanding:

Input per Serial -> String gets split into four pieces (input are 4 HEX numbers in one piece) -> convert every single piece into a seperate decimal number

I already got a little bit of code but I cant figure out how to split a string exectly after every two characters or number because I want to split the string after every hex number.

const long baud_rate = 19200;

String input;

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

void loop() {
 if (Serial.available()) {
    input = Serial.readString();
    input.trim(); // strip off any leading/trailing space and \r \n
    if (input.length() > 0) {  // got some input handle it
      input.toUpperCase();
      Serial.println(input);
    }
  }
}

So it should look like this when it works:

Input: ebcb1900

split output:

1.) EB
2.) CB
3.) 19
4.) 00

decimal output:

1.) 235
2.) 203
3.) 25
4.) 00

The best option would be that every character that is too much in the serial input gets trashed if someone miss clicks.

This might help
https://docs.arduino.cc/built-in-examples/strings/StringSubstring/

Okay thx. I hope that my tests are correct that the end pointer is the n+1 when I want to show n?

You will, of course, be testing the length of the String and rejecting anything too short or too long before processing it. You should also check that any characters received are valid characters for a HEX input

If you are going to do that then you might consider reading the input another way

I looked into but I think my code is garbage :smiley:
Maybe someone has a better idea instead of converting back and forth

const long baud_rate = 19200;


char input[8];
char char1[3];
String str;
String output;
int val;

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

void loop() {
  if (Serial.available() > 0) {
    Serial.readBytesUntil('\n', input, 8);

    str = input;
    output = str.substring(0, 2);
    output.toCharArray(char1, output.length() + 1);
    val = StrToHex(char1);
    Serial.println(val);
  }
}

int StrToHex(char str[])
{
  return (int) strtol(str, 0, 16);
}

Also it puts out two lines but I only want one line to be written.

look this over

input

ebec 1900

output

  0: 0xeb  235
  1: 0xcb  203
  2: 0x19   25
  3: 0x00    0
const long baud_rate = 19200;

int  val [4];
char s [90];

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


void loop() {
    if (Serial.available() > 0) {
        char input [50];
        int n = Serial.readBytesUntil('\n', input, sizeof(input)-1);
        input [n] = '\0';

        sscanf (input, "%02x%02x%02x%02x",
            & val [0], & val [1], & val [2], & val [3] );

        for (int n = 0; n < 4; n++) {
            sprintf (s, " %2d: 0x%02x %4d", n, val [n], val [n]);
            Serial.println (s);
        }
    }
}

@gcjr thx for that short example.
I have another question depending on that thread.

I want to control a four pwm pins with a 100Hz pwm signal with those int values. Therefor I found a short information but I am not a software developer. So my question is why is the maximum dutycycle increment only 1-77?

void setup(){
  //Initialize Timer2
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2 = 0;

  // Set OC2B for Compare Match (digital pin3)
  pinMode(3, OUTPUT);
  bitSet(TCCR2A, COM2B1);//clear OC2B on up count compare match
  //set OC2B on down count compare match

  // Set mode 5-- Phase correct PWM to OCR2A counts up and down
  bitSet(TCCR2A, WGM20);
  bitSet(TCCR2B, WGM22);

  // Set up /1024 prescale
  bitSet(TCCR2B, CS20);
  bitSet(TCCR2B, CS21);
  bitSet(TCCR2B, CS22);
  
  OCR2A = 78; //Sets freq 100Hz
  //Timer 2 counts up and down for 156 total counts
  //156 x 1024 x.0625 = 9.98ms ~ 100 Hz

  //duty cycle is set by OCR2B value
  //valid values 1-77
  //change it in loop to vary duty cycle
  OCR2B = 38;//50% duty cycle
}

So as it looks for me its not possible to get a PWM for an output of an Arduino Uno with a frequency of 100Hz and a range of dutycycle of 0-255?
Because I would loose a lot of steps if I would just calculate the dutycycle out of 0-255.

So after some reading and thinking. Is it possible to change the prescaler so that I get a dutycycle range from 0-255 but I can keep my pwm frequency at 100Hz?
Also is it possible to set up the same for timer 1, so that I can use pin 3, 11 and 10, 9?

Here's another solution to your original question.

int output[6];
char buff [12];
byte d;
int buffSize, i, j;


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

void loop() {

  if (Serial.available()) {               // process input from Serial Monitor

    d = Serial.read();                   // set end-line option to Newline or CR
    if ((d == 13) || (d == 10)) {
      buff[buffSize] = 0;
      j = 0;
      for (i = 0; i < buffSize; i += 2) {
        output[j] = (buff[i] << 4) + buff[i + 1];
        j += 1;
      }

      for (i = 0; i < j; i++) {
        Serial.println (output[i], HEX);
      }
       Serial.println();

      for (i = 0; i < j; i++) {
        Serial.println (output[i]);
      }
       Serial.println();
      buffSize = 0;
    }
    else {
      // add error checking here

      if (d > 0x39) d -= 7;
      d &= 0xF;
      buff[buffSize] = d;
      buffSize++;
    }
  }
}

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