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");
}
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 ofdehex(hin[i])<<4are clear, and so are the high 4 bits ofdehex(hin[i+1]). – James Waldby - jwpat7 May 15 '17 at 15:31010307E40001C549should return me (as ASCII \code)\01\03\07\E4\00\01\C5Ior (as U8)[1,3,7,228,0,1,197,73]Instead I'm getting (as ASCII)\100~@\EEany thoughts? – ATE-ENGE May 15 '17 at 15:48\100~@\EEequates to (as U8)[16,48,126,64,238]– ATE-ENGE May 15 '17 at 15:56+instead of|you have a precedence error. See my edit. – Majenko May 15 '17 at 15:57|for 010307E40001C549 I'm still getting(as ASCII)
\100~@\EEequates to (as U8)[16,48,126,64,238]Updated Code above – ATE-ENGE May 15 '17 at 16:09i++instead ofi+=2which is wrong. Check my example (pure c) code for how to do it. – Majenko May 15 '17 at 16:13