0

The Code Below now works:

void SendCTRL (String &input) 
{
 const char *hin = input.c_str(); // Get character array
 int clen = input.length()/2;
 unsigned char cmd[clen+1]; // Leave a byte for null terminator
 for (int i=0; i < 2*clen; i+=2)
 {
 cmd[i/2] = dehex(hin[i])<<4 | dehex(hin[i+1]);
 }
 cmd[clen] = 0; // Null-byte terminator
 digitalWrite(SSerialTxControl, RS485Transmit); // Enable RS485 Transmit 
 for (int i=0; i< clen; i++)
 {
 RS485Serial.write(cmd[i]); // Send string someplace
 //Serial.write(cmd[i]);
 }
 delay(clen/4);
 digitalWrite(SSerialTxControl, RS485Receive); // Disable RS485 Transmit
 Serial.println();
}
byte dehex(char c) 
{
 // Get nibble value 0...15 from character c
 // Treat digit if c<'A', else letter
 return c<'A'? c & 0xF : 9 + (c & 0xF);
}
byte dehex(char c) 
{
 // Get nibble value 0...15 from character c
 // Treat digit if c<'A', else letter
 return c<'A'? c & 0xF : 9 + (c & 0xF);
}

Input is a series of ASCII-encoded hex digits and getting the output to print the byte values of the hex.

asked May 15, 2017 at 14:15

1 Answer 1

2

There's some logic slightly askew with your length calculations:

int clen = input.length()/2;

Ok, so for a (say) 20 character string you have clen=10.

for (int i=0; i < clen; i+=2)

Ok, so for the first 10 characters of your 20 character string you take alternate ones (0, 2, 4, 6, 8)

What about the last 10 characters? clen is 10, not 20, since you divided it by 2 at the start.

Decide if you want clen to be half the string length, then count double, or is the whole string length, and you divide it by 2 where you want the final string length. Or have two variables - one before and one after dividing by 2.

Oh, and you should pass your String parameter by reference so you don't duplicate the object and end up fragmenting your heap.

void SendCTRL (String &input) 

I haven't gone into depth about the working of your dehex function, but this is the function I always use and works well:

unsigned char h2d(char hex)
{
 if(hex > 0x39) hex -= 7; // adjust for hex letters upper or lower case
 return(hex & 0xf);
}

Also you should or your values together, not add them:

cmd[i/2] = (dehex(hin[i])<<4) | dehex(hin[i+1]);

This would go some way to fixing your current issue, since | has a different precedence to +. At the moment you have effectively:

cmd[i/2] = dehex(hin[i]) << (4 + dehex(hin[i+1]));

since the + happens before the <<, whereas what you want is:

cmd[i/2] = (dehex(hin[i]) << 4) + dehex(hin[i+1]);

However with | instead you get

cmd[i/2] = (dehex(hin[i]) << 4) | dehex(hin[i+1]);

because the << happens before the |

Here is your code written in pure C to run on a PC (faster to debug and test than an Arduino when you're on Linux):

#include <stdio.h>
#include <string.h>
unsigned char dehex(char c)
{
 // Get nibble value 0...15 from character c
 // Treat digit if c<'A', else letter
 return c<'A'? c & 0xF : 9 + (c & 0xF);
}
void SendCTRL (const char *hin)
{
 int ilen = strlen(hin);
 int clen = ilen / 2;
 unsigned char cmd[clen+1]; // Leave a byte for null terminator
 for (int i=0; i < ilen; i+=2)
 {
 cmd[i/2] = dehex(hin[i])<<4 | dehex(hin[i+1]);
 printf("%02x\n", cmd[i/2]);
 }
 cmd[clen] = 0; // Null-byte terminator
 for (int i = 0; i < clen; i++) {
 printf("%c", cmd[i]);
 }
}
void main() {
 SendCTRL("010307E40001C549");
}
answered May 15, 2017 at 14:21
10
  • Ok! that got the writing working. Unfortunately, it just seems to output jibberish. Commented May 15, 2017 at 15:09
  • 1
    I have posted my version of a hex to dec converter. It may work better, or may not... Commented May 15, 2017 at 15:12
  • 1
    @Majenko, c<'A'? c & 0xF : 9 + (c & 0xF) will work with a...f as well as A...F as representatives of 0xA...0xF. Also, Addition vs Or makes no difference here, because the low 4 bits of dehex(hin[i])<<4 are clear, and so are the high 4 bits of dehex(hin[i+1]). Commented May 15, 2017 at 15:31
  • 1
    @JamesWaldby-jwpat7 yes, it should all work fine in this situation - but it's good practice to get into the habit of combining with OR rather than with ADD. Commented May 15, 2017 at 15:33
  • 1
    Because you're using + instead of | you have a precedence error. See my edit. Commented May 15, 2017 at 15:57

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.