Byte* to unsigned char

Hi all, I’m here in desperation after trying many different approaches to finding a way to display my info from the callback to a 0.96 oled, i figured a little guidance my spur things along.

So… here’s my sketch, (see next post) i am trying to do two versions of this, one for my uno, and one on an esp8266, but i have the same issue for both.

So everything is working up to the point where i am using else if statements to display several status messages on the oled, and this one in particular:

 else if (String(topic) == "MyMQTT/25/2/V_TEMP") {
//Serial.println(msgString);
    sendCharXY(payload, 2, 0);
  }

I get errors converting the payload (byte* aka unsigned char*) to unsigned char, i have tried using the sendStrXY function also, and it is also giving errors, and the only success i had was by trying to deref the byte* using payload* instead of payload, but this only display the first digit of the temp payload.

So basically i am looking for some clear noobstyle uncomplicated pointers just to get me moving again with this project.

Thanks.

#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <IPAddress.h>

#include <Wire.h>  //For oled

//---------------FONT + GRAPHIC-----------------------------//
#include "data.h"

// OLED I2C bus address
#define OLED_address  0x3c


const char* ssid = "sieze";
const char* password = "ushallno";

char* topic = "#";     //  using wildcard to monitor all traffic from mqtt server
char* server = "192.168.0.7";  // Address of my server on my network, substitute yours!

char message_buff[100];   // initialise storage buffer (i haven't tested to this capacity.)


WiFiClient wifiClient;
PubSubClient client(server, 1883, callback, wifiClient);


String macToStr(const uint8_t* mac)
{
  String result;
  for (int i = 0; i < 6; ++i) {
    result += String(mac[i], 16);
    if (i < 5)
      result += ':';
  }
  return result;
}

void setup() {
  Serial.begin(115200);
  delay(10);


  // Set SDA & SCL for ESP8266 to:
#ifdef ARDUINO_ESP8266_ESP01
  Wire.pins(0, 2); //0=SDA, 2=SCL, 2 also =LED
#endif

  // Initialize I2C and OLED Display
  Wire.begin();
  init_OLED();
  reset_display();           // Clear logo and load saved mode


  for (int i = 0; i < 128 * 8; i++) // show 128* 64 Logo
    SendChar(pgm_read_byte(logo + i));
  delay(8000);
  displayOn();
  clear_display();



  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);


  WiFi.begin(ssid, password);
  WiFi.config(IPAddress(192, 168, 0, 58), IPAddress(192, 168, 0, 1), IPAddress(255, 255, 255, 0));

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  sendStrXY("IP OK", 0, 0);
  delay(1000);
  //  connection to broker script.
  if (client.connect("arduinoClient")) {
    client.publish("outTopic", "hello world");
    client.subscribe("esprelaytest");   // i should probably just point this to the variable above.
    client.subscribe("MyMQTT/25/2/V_TEMP"); // Jared room
    client.subscribe("MyMQTT/25/4/V_LIGHT");
    client.subscribe("MyMQTT/25/5/V_LIGHT");
    Serial.println("Broker connected");
    sendStrXY("Broker OK", 1, 0);
    //delay(1000);
    //clear_display();
  }
  else {
    sendStrXY("Broker bad", 1, 0);
    Serial.println("MQTT connect failed");
    Serial.println("Will reset and try again...");
    delay(2000);
    abort();
  }
  

}

void loop() {

  client.loop();
}

//

void callback(char* topic, byte* payload, unsigned int length) {
  
  int i = 0;

  Serial.println("Message arrived:  topic: " + String(topic));
  Serial.println("Length: " + String(length, DEC));

  // create character buffer with ending null terminator (string)
  for (i = 0; i < length; i++) {
    message_buff[i] = payload[i];
  }
  message_buff[i] = '\0';

  String msgString = String(message_buff);

  Serial.println("Payload: " + msgString);


  if (String(topic) == "MyMQTT/25/4/V_LIGHT" && msgString == "1") {   // if there is a "1" published to any topic (#) on the broker then:

    sendStrXY("Relay 1  ON", 0, 0);
  }
  else if (String(topic) == "MyMQTT/25/4/V_LIGHT" && msgString == "0") {

    sendStrXY("Relay 1 OFF", 0, 0);
  }
  else if (String(topic) == "MyMQTT/25/5/V_LIGHT" && msgString == "1") {

    sendStrXY("Relay 2  ON", 1, 0);
  }
  else if (String(topic) == "MyMQTT/25/5/V_LIGHT" && msgString == "0") {

    sendStrXY("Relay 2 OFF", 1, 0);
  }
  
  else if (String(topic) == "MyMQTT/25/2/V_TEMP") {
//Serial.println(msgString);
    sendCharXY(payload, 2, 0);
  }


}
// Turns display on.
void displayOn(void)
{
  sendcommand(0xaf);        //display on
}
// Prints a display char (not just a byte) in coordinates X Y,
// being multiples of 8. This means we have 16 COLS (0-15)
// and 8 ROWS (0-7).
static void sendCharXY(unsigned char data, int X, int Y)
{
  setXY(X, Y);
  Wire.beginTransmission(OLED_address); // begin transmitting
  Wire.write(0x40);//data mode

  for (int i = 0; i < 8; i++) //8
    Wire.write(pgm_read_byte(myFont[data - 0x20] + i));

  Wire.endTransmission();    // stop transmitting
}

// Set the cursor position in a 16 COL * 8 ROW map.
static void setXY(unsigned char row, unsigned char col)
{
  sendcommand(0xb0 + row);              //set page address
  sendcommand(0x00 + (8 * col & 0x0f)); //set low col address  //8
  sendcommand(0x10 + ((8 * col >> 4) & 0x0f)); //set high col address  //8

}
// Turns display off.
void displayOff(void)
{
  sendcommand(0xae);		//display off
}

// Clears the display by sendind 0 to all the screen map.
static void clear_display(void)
{
  unsigned char i, k;
  for (k = 0; k < 8; k++) //8
  {
    setXY(k, 0);
    {
      for (i = 0; i < 128; i++) //was 128
      {
        SendChar(0);         //clear all COL
      }
    }
  }
}
// Actually this sends a byte, not a char to draw in the display.
// Display's chars uses 8 byte font the small ones and 96 bytes
// for the big number font.
static void SendChar(unsigned char data)
{
  Wire.beginTransmission(OLED_address); // begin transmitting
  Wire.write(0x40);//data mode
  Wire.write(data);
  Wire.endTransmission();    // stop transmitting
}



// Resets display depending on the actual mode.
static void reset_display(void)
{
  displayOff();
  clear_display();

  displayOn();
}

// Prints a string in coordinates X Y, being multiples of 8.
// This means we have 16 COLS (0-15) and 8 ROWS (0-7).
static void sendStrXY( char *string, int X, int Y)
{
  setXY(X, Y);
  unsigned char i = 0;
  while (*string)
  {
    for (i = 0; i < 8; i++)
    {
      SendChar(pgm_read_byte(myFont[*string - 0x20] + i));
    }
    *string++;
  }
}
// Used to send commands to the display.
static void sendcommand(unsigned char com)
{
  Wire.beginTransmission(OLED_address);     //begin transmitting
  Wire.write(0x80);                          //command mode
  Wire.write(com);
  Wire.endTransmission();                    // stop transmitting
}

// Inits oled and draws logo at startup
static void init_OLED(void)
{
  sendcommand(0xae);		//display off
  sendcommand(0xa6);            //Set Normal Display (default)
  // Adafruit Init sequence for 128x64 OLED module
  sendcommand(0xAE);             //DISPLAYOFF
  sendcommand(0xD5);            //SETDISPLAYCLOCKDIV
  sendcommand(0x80);            // the suggested ratio 0x80
  sendcommand(0xA8);            //SSD1306_SETMULTIPLEX
  sendcommand(0x2F); //--1/48 duty    //NEW!!!
  sendcommand(0xD3);            //SETDISPLAYOFFSET
  sendcommand(0x0);             //no offset
  sendcommand(0x40 | 0x0);      //SETSTARTLINE
  sendcommand(0x8D);            //CHARGEPUMP
  sendcommand(0x14);
  sendcommand(0x20);             //MEMORYMODE
  sendcommand(0x00);             //0x0 act like ks0108

  sendcommand(0xA0 | 0x1);      //SEGREMAP   //Rotate screen 180 deg
  //sendcommand(0xA0);

  sendcommand(0xC8);            //COMSCANDEC  Rotate screen 180 Deg
  //sendcommand(0xC0);

  sendcommand(0xDA);            //0xDA
  sendcommand(0x12);           //COMSCANDEC
  sendcommand(0x81);           //SETCONTRAS
  sendcommand(0xCF);           //
  sendcommand(0xd9);          //SETPRECHARGE
  sendcommand(0xF1);
  sendcommand(0xDB);        //SETVCOMDETECT
  sendcommand(0x40);
  sendcommand(0xA4);        //DISPLAYALLON_RESUME
  sendcommand(0xA6);        //NORMALDISPLAY

  clear_display();
  sendcommand(0x2e);            // stop scroll

  sendcommand(0x20);            //Set Memory Addressing Mode
  sendcommand(0x00);            //Set Memory Addressing Mode ab Horizontal addressing mode


  setXY(0, 0);
  /*
  for(int i=0;i<128*8;i++)     // show 128* 64 Logo
  {
    SendChar(pgm_read_byte(logo+i));
  }
  */
  sendcommand(0xaf);		//display on
}

I didn't study all code but maybe it helps. If the "payload" variable is (byte *), pointer to the byte in other words, use "*payload" to obtain value at the address (pointer) or "payload[0]" - the first element of an array do the same.

Operator * accresses a value through a pointer.

else if (String(topic) == "MyMQTT/25/2/V_TEMP") {
//Serial.println(msgString);
    sendCharXY(*payload, 2, 0);
//

Gambituk:

 else if (String(topic) == "MyMQTT/25/2/V_TEMP") {

//Serial.println(msgString);
    sendCharXY(payload, 2, 0);
  }



I get errors converting the payload (byte* aka unsigned char*) to unsigned char, i have tried using the sendStrXY function also, and it is also giving errors, and the only success i had was by trying to deref the byte* using payload* instead of payload, but this only display the first digit of the temp payload.

So basically i am looking for some clear noobstyle uncomplicated pointers just to get me moving again with this project.

Thanks.

That is as expected. Your sendCharXY() funtion only prints a single character, and therefore only takes a single character (not a pointer to a character string) as its data parameter.

If you want to print more than one character as bytes, you need to call it something like:

else if (String(topic) == "MyMQTT/25/2/V_TEMP") {
    //Serial.println(msgString);
    for (int i=0; payload[i] != 0; i++)
    {
        sendCharXY(payload[i], 2, 0);
    }
}

By the way, I'm a little surprised that your "if (String(topic) == "MyMQTT/25/2/V_TEMP")" works. You are using a String Object, and should be using the "String(). equals()" method.

Because of the operator == (const char *) is defined, it should work.

Budvar10:
Because of the operator == (const char *) is defined, it should work.

My bad. When I first looked, I didn't see it defined in the Arduino StringObject class.

Thanks, your answers and comments have brought me to this code, which allows me to print the whole payload.

  else if (String(topic) == "MyMQTT/25/2/V_TEMP") {
//Serial.println(msgString);
    sendCharXY(payload[0], 2, 0);
    sendCharXY(payload[1], 2, 1);
    sendCharXY(payload[2], 2, 2);
    sendCharXY(payload[3], 2, 3);
  }

I didn't know it was possible to just add a reference to the index, and i was previously using the sendStrXY function, so assumed that the sendCharXY function would also print all the data not just 1 byte.

Thanks for the help.

ps. If there is a tidier way of doing that ^ i would love to learn more.

Thanks

Gambit