Go Down

### Topic: Help with strtoul() function. (Read 3306 times)previous topic - next topic

#### Pavilion1984

##### Apr 06, 2012, 12:26 pmLast Edit: Apr 06, 2012, 12:34 pm by Pavilion1984 Reason: 1
Hello all.

New to world of Arduino and as a electronic hardwear engineer this programing side is all new to me but learning fast thanks to the forums  .

Ok, i would like to use the function strtoul() but i don't fully understand how to use it so would like your help in understanding how to use the function correctly.

I have a ASCII string for example,

"41 05 1C 7B" (received over the serial)

but i'm only interested in the "1C 7B" and would like to convert it to HEX to get something like "0x1C7B" stored to a unsigned long. So if anyone could show/explain this to me it will be a great help.

Look forward to your replies, thanks.

#### Marek080

#1
##### Apr 06, 2012, 01:05 pm
The following code assumes that you save the whole ASCII string into a character array (reading from serial is usually a slow process with characters arriving one after another).

Code: [Select]
`char buffer[12]; //your message with a trailing '\0'// read from serial and maybe check if message has the correct lengthchar * pch;uint32_t nResult= 0;byte nPos= 0;pch= strtok(buffer, " ");while(pch){  if(nPos > 1) // ignore first and second hex value  {    nResult= (nResult << 8) | (strtoul(pch, NULL, 16) & 0xff);  }  nPos++;  pch= strtok(NULL, " ");}`
The code is not efficient or fail save. Basically your string is divided into smaller substrings and in the loop the first two "bytes" are skipped and the following bytes are combined to the result by reading a single byte (result from stroul is 32 bit, hence the mask to 8 bit) and shifting the previous value of the result by 8 bits and placing the read byte into this now free space.

Another approach would be to modify the buffer directly to get those two bytes of interest together without the space in between and then use strtoul().
loved the 68000 assembler back then and now I have to deal with THIS 8 bit thingy

#### bubulindo

#2
##### Apr 06, 2012, 01:12 pm
Something like this?
Code: [Select]
`char str[] = {'4','1','0','5','1','C','7','B','\0'};unsigned long result = strtoul(str, NULL, 16); unsigned int result_int;result = result &0xFFFF; //getting rid of 0x4105//ORresult_int = result &0xFFFF; //getting rid of 0x4105`

Should work.
I haven't compiled it... so chances are that this may put out some errors.
Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

#### Pavilion1984

#3
##### Apr 06, 2012, 01:40 pmLast Edit: Apr 06, 2012, 02:08 pm by Pavilion1984 Reason: 1
Thanks for the replies an will have a look at them. From searching around i came up with the below, whould that not work do you think?

#define NULL '\0'

char serialrx[16];
char buffer[8];

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

void loop() {
byte i = 6;
serialrx[6];                                                     //start conversion from the 6th byte
while(serialrx != NULL)
buffer[i++] = strtoul (serialrx, NULL, 16);
i = 6;

}

#### Marek080

#4
##### Apr 06, 2012, 05:43 pm
Please use the code tags (button # above the smilies).

Concerning the code you posted:
Code: [Select]
`#define NULL '\0'`
This one is not necessary.
Code: [Select]
`char serialrx[16];char buffer[8];void setup() {  Serial.begin(9600);  Serial.flush();}`
Serial.flush() changed in Arduino 1.0. Before it cleared the receive buffer. Since v1.0 it waits for the transmit buffer to be empty / the transmission to be finished. Not really necessary in setup().
Code: [Select]
`void loop() {  byte i = 6;  serialrx[6];                                                     //start conversion from the 6th byte`
This line does nothing.
Code: [Select]
`  while(serialrx != NULL)  buffer[i++] = strtoul (serialrx, NULL, 16);  i = 6;}`
And this code is bogus. serialrx is a pointer to an array of characters. serialrx[pos] means one of the characters in the array. This looks like a try in using pointer arithmetics or maybe some very old code for reading the serial receive buffer. The way it is now serialrx is never NULL because it is defined as a global array - the pointer to the array stored in serialrx is not NULL.

From my point you need to learn some of the C programming basics and some C++ to use libraries supplied with Arduino.

Lets go through all step by step. Let us assume all input via serial connection looks like your example string - four hex coded values with spaces between and at the end of the command an "return" ("\n" or "\n\r"). First step is to get the input from Serial. All data arrives bytewise and the ATmega328 on the Arduino is a lot faster than the transmission via Serial. You could use a buffer for the incoming data and when a "return" arrives the whole string is evaluated. While reading data you could filter the spaces out and ignore any '\r' only looking for '\n'. This helps for the second step using strtoul like bubulindo did in his post. For the reading you need some kind of a loop which collects and filters incoming data.
Code: [Select]
`  boolean bWaitingInput= true;  while(bWaitingInput)  {    uint8_t nBufferPos= 0; // position in the array where a new character is saved    if(nBufferPos >= BUFFER_MAX) // is the buffer full?    {      serialrx[BUFFER_MAX - 1]= '\0'; // make a valid string by setting the last buffer character to '\0'      Serial.print("buffer overflow: ");      Serial.println(serialrx); // transmit what the buffer holds for debugging      nBufferPos= 0; // reset the buffer    }    if(Serial.available()) // something arrived via serial connection?    {      char c= Serial.read(); // read the new character      switch(c)      {        case '\r':        case ' ':          break; // do nothing with space or '\r'        case '\n':          serialrx[nBufferPos++]= '\0'; // a string must have 0 at the end, so we add it here          bWaitingInput= false; // we have data for evaluation          break;        default: // all other characters go into the buffer          serialrx[nBufferPos++]= c;    }  }  Serial.print("received: ");  Serial.println(serialrx);`
Now strtoul could be used on serialrx (no spaces to interfere are in the buffer). BUFFER_MAX is a define for the buffer size. Search for "post increment" to understand the filling of the buffer with the position variable. This is for a start. If you have no idea what's going on then use Serial.println() to show you results in the serial monitor. PaulS proposes to use a pen and paper and think of what you would do step by step to get your problem solved - I like this idea.
loved the 68000 assembler back then and now I have to deal with THIS 8 bit thingy

Go Up

Please enter a valid email to subscribe