MCP23017 16-Bit I/O Expander with wire.h - String to Byte

Hey. I'm quite stuck in what I need to do to fix my issue. Essentially I an arduino as a client which receives a string from a server. The string is of hex values such as "0x00; 0xFF; 0x20 " which is then parsed out by the arduino into a string array. This string array is then used to assign these now parsed values to the MCP 23017 outputs which then switch relays. I am unsure of how I can get my String array to byte without loosing any values. Sorry I'm not the best at explaining.

Here's the code for parsing and switching the relay.

String serverMsg;
String parsedMsg[50];

while (client.available() > 0) {
    serverMsg = client.readString();
    int r = 0, t = 0;

    for (int i = 0; i < serverMsg.length(); i++)
    {
      if (serverMsg[i] == ' ' || serverMsg[i] == ';')
      {
        if (i - r > 1)
        {
          parsedMsg[t] = serverMsg.substring(r, i);
          t++;
        }
        r = (i + 1);
      }
    }
    Serial.println(parsedMsg[1]);
    //    for (int k = 0; k <= t; k++)
    //    {
    //      Serial.println(parsedMsg[k]);
    //    }
  }

    Wire.beginTransmission(0x20);
    Wire.write(0x12);      // address bank A
    Wire.write((byte)(parsedMsg[1]));  // value to send - all HIGH
    Wire.endTransmission();

    Wire.beginTransmission(0x20);
    Wire.write(0x13);      // address bank B
    Wire.write((byte)(parsedMsg[2]));  // value to send - all HIGH
    Wire.endTransmission();

You are sending a String which contains a text representation of some hexadecimal values such as "0x00; 0xFF; 0x20 ".
From this String, you are attempting to form pairs of bytes which are to control the ports of an MCP23017 port expander.
Is that all correct?

Where in your parsing are you looking for the prefix "0x" ?

If you get a number in the form of a pair of characters, e.g. "56" from "0x56" you can convert these to a byte by subtracting '0'.

char hexWord[5] = "0x56" ;  // or use strcpy() / strncpy() etc. to fill an existing char array
byte digit1 = hexWord[2] - '0' ;  // 5
byte digit2 = hexWord[3] - '0' ;  // 6

If it is a letter, say in the range 'A' to 'F', subtract 'A' and add the offset 10.

Thanks for the comment. I never thought in my parsing to look for "0x". I was parsing it based on spaces " " and semicolons ";". These were then to be parsed such as "0x00; 0xFF; 0x20" into separate values:

parsedMsg[0] = "0x00"
parsedMsg[1] = "0xFF"
parsedMsg[2] = "0x20"

These arrays would then be placed in the code for each relay card (there is 8 as that is the maximum MCP23017s i can use on an arduino due to addressing.) But i am having trouble as wire.h only accepts in bytes rather than strings/string arrays

maybe some thing like this:
(compiles, NOT tested!)

#include <Wire.h>

void update_MCP23017(uint8_t addr, uint8_t value) {
  Wire.beginTransmission(0x20);
  Wire.write(addr);      // address bank
  Wire.write(value);  // value to send
  Wire.endTransmission();
}

void setup() {

  String serverMsg;
  char parsedMsg[50];
  char delimiters[] = " ;";


  Serial.begin(115200);

  while (client.available() > 0) {
    serverMsg = client.readString();
    serverMsg.toCharArray(parsedMsg, 50);
    char * pch;
    int i = 0;
    pch = strtok (parsedMsg, delimiters);
    while (pch != NULL)
    {
      Serial.println (pch);
      if (i == 1) update_MCP23017(0x12, (int) strtol(&pch[2], 0, 16)); //&pch[2] -> dont need the "0x" in the substring to convert hex string to int ;)
      else if (i == 2) update_MCP23017(0x13, (int) strtol(&pch[2], 0, 16));
      pch = strtok (NULL, delimiters);
      ++i;
    }
  }
}

void loop() {

}

hope that helps....

1 Like

Thanks for the help! I'm just getting confused in what this does here, especially 0, 16.

https://www.cplusplus.com/reference/cstdlib/strtol/

16 == base 16 ie hexadecimal :wink:

1 Like