Firstly, excuse my poor English, this is not my native langage.

I'm trying to use an Arduino Uno to drive an 8 relay board from an MQTT Subscription. I ask for help because i'm some kind of beginner in arduino, i'm just a Linux addict.

The idea is to get a payload from PubSubclient and use it to manage relays. For example, the payload '71' ask the relay 7 to turn on and '42' make the relay 4 to turn off.

All works fine until I wanted to write a function with two parameters : 'relay_number' and 'Action'

All parameters are received but the relay never goes up or down.

My code :

void callback(char* topic, byte* payload, unsigned int length) {
  Relay_Nb = (char)payload[0];
  Action = char(payload[1]);

  RelayControl(Relay_Nb, Action);

void RelayControl(char Relay_Nb, char Action) {
  Serial.println(Relay_Nb);   // for debugging purpose
  if ( Action == '0') {
    Serial.print("Bringing down Relay ");
    digitalWrite(Relay_Nb, LOW); 
  } else if (Action == '1') {
    Serial.print("Bringing up Relay ");
    digitalWrite(Relay_Nb, HIGH);
  } else if (Action == '2') {
    // Relay temporisé (ouverture portail par ex)
    Serial.println("Bringing up, and down Relay ");
    digitalWrite(Relay_Nb, HIGH);
    digitalWrite(Relay_Nb, LOW);

I'm sure an old maker have the solution i'm searching for hours now.

Please help and don't hesitate to show me others ways. Thanks.

  • 2
    What is the serial output? Aug 9, 2020 at 18:27
  • Relay_Nb is the character 1 or 0, not the value 1 or 0?
    – Majenko
    Aug 9, 2020 at 18:27
  • The serial output is for debugging purpose. Character or value is probably the problem, but what have i to do to change this?
    – Pwol
    Aug 9, 2020 at 18:49
  • your callback function makes an assumption about the data ... there is no check for unexpected data
    – jsotola
    Aug 9, 2020 at 19:05
  • You're right.I'll write it after the relay issue.
    – Pwol
    Aug 9, 2020 at 19:32

1 Answer 1


You are sending the parameter Relay_Nb as a character, and then using it as an integer.

You need to turn the character into an integer - and the simplest way is to subtract the ASCII value of 0 from it:

Relay_Nb = payload[0] - '0';

But with that said, a note on how you have written your callback:

  • You aren't checking the data is valid.

You should really be doing, at the very least, the following:

  1. Check that the length parameter is at least 2,
  2. Check that the two data values are within the correct range for your function
  • It works fine, you're my hero. I just don't understand how. Where can I find some explaination ? I can now start the security checks.
    – Pwol
    Aug 9, 2020 at 20:02
  • @Pwol: man ascii, and look for the code points of the digits. Aug 9, 2020 at 20:25
  • @EdgarBonet You're assuming he's using a real operating system, not some toy like Windows.
    – Majenko
    Aug 9, 2020 at 20:31
  • 1
    @PeterFeerick atoi() expects a string, not a character. Sep 9, 2020 at 11:01
  • 1
    Or Relay_Nb = payload[0] & byte(0x0f); That's why ASCII for 0 to 9 was encoded as 0x30 to 0x39, i.e. easy conversion between bytes and characters.
    – tim
    Sep 9, 2020 at 23:44

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.