Variable Types - not getting it.

I’m stuck.

I have two pieces of code I need to put together. But the variabel types have me going in circles.

I have this piece for MQTT publishing

/*
 Example of using a Stream object to store the message payload

 Uses SRAM library: https://github.com/ennui2342/arduino-sram
 but could use any Stream based class such as SD

  - connects to an MQTT server
  - publishes "hello world" to the topic "outTopic"
  - subscribes to the topic "inTopic"
*/

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <SRAM.h>

// Update these with values suitable for your network.
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(172, 16, 0, 100);
IPAddress server(172, 16, 0, 2);

SRAM sram(4, SRAM_1024);

void callback(char* topic, byte* payload, unsigned int length) {
  sram.seek(1);

  // do something with the message
  for(uint8_t i=0; i<length; i++) {
    Serial.write(sram.read());
  }
  Serial.println();

  // Reset position for the next message to be stored
  sram.seek(1);
}

EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient, sram);

void setup()
{
  Ethernet.begin(mac, ip);
  if (client.connect("arduinoClient")) {
    client.publish("outTopic","hello world");
    client.subscribe("inTopic");
  }

  sram.begin();
  sram.seek(1);

  Serial.begin(9600);
}

void loop()
{
  client.loop();
}

And I want to include this piece:

//KY015 DHT11 Temperature and humidity sensor 
int DHpin = 8;
byte dat [5];
 
void setup () {
  Serial.begin (9600);
  pinMode (DHpin, OUTPUT);
}
 
void loop () {
  start_test ();
  Serial.print ("Current humdity =");
  Serial.print (dat [0], DEC); // display the humidity-bit integer;
  Serial.print ('.');
  Serial.print (dat [1], DEC); // display the humidity decimal places;
  Serial.println ('%');
  Serial.print ("Current temperature =");
  Serial.print (dat [2], DEC); // display the temperature of integer bits;
  Serial.print ('.');
  Serial.print (dat [3], DEC); // display the temperature of decimal places;
  Serial.println ('C');
  delay (700);
}

byte read_data () {
  byte data;
  for (int i = 0; i < 8; i ++) {
    if (digitalRead (DHpin) == LOW) {
      while (digitalRead (DHpin) == LOW); // wait for 50us
      delayMicroseconds (30); // determine the duration of the high level to determine the data is '0 'or '1'
      if (digitalRead (DHpin) == HIGH)
        data |= (1 << (7-i)); // high front and low in the post
      while (digitalRead (DHpin) == HIGH); // data '1 ', wait for the next one receiver
     }
  }
return data;
}
 
void start_test () {
  digitalWrite (DHpin, LOW); // bus down, send start signal
  delay (30); // delay greater than 18ms, so DHT11 start signal can be detected
 
  digitalWrite (DHpin, HIGH);
  delayMicroseconds (40); // Wait for DHT11 response
 
  pinMode (DHpin, INPUT);
  while (digitalRead (DHpin) == HIGH);
  delayMicroseconds (80); // DHT11 response, pulled the bus 80us
  if (digitalRead (DHpin) == LOW);
  delayMicroseconds (80); // DHT11 80us after the bus pulled to start sending data
 
  for (int i = 0; i < 4; i ++) // receive temperature and humidity data, the parity bit is not considered
    dat[i] = read_data ();
 
  pinMode (DHpin, OUTPUT);
  digitalWrite (DHpin, HIGH); // send data once after releasing the bus, wait for the host to open the next Start signal
}

The Temp and Humidity don’t need to be as “long winded” as that. Simply the two values on a line separated by a couple of spaces.

I got that part but then I ran into problems with the variable TYPES.

char, byte, string and so on.

I get that they are different and do different things, but I can’t get why it seems to hard to convert from one to another type.

I got the line of text (I’m not going to qualify that any more/further because I will probably call it the wrong thing and not be helped with that) and it “Serial.print” ok.

But then trying to put it in the MQTT message… Nothing works.

The line of interest is this one:

client.publish("outTopic","hello world");

Ok, so I made it a different Topic, but replacing “hello world” with the text is impossible.

I make it into a “string” so I can build up the string as I go along is/was easy enough, but then it said it wants char where the “hello world” is.

I go off and look at char and there are two types: char() and char*.

Seems I can make char() ok, but not char* - and that is what is wanted. The one I can’t get.

I’ve read about string2char() and other such functions, but all I seem to do is go in circles getting no where.
And being the wrong one, doesn’t really help me anyway.

Could someone explain / help me understand what is going on and how to make the acceptable format data for the command to use and send?

Thanks in advance.

char* is a pointer to a char. Let this be your first introduction to pointers. It's not as hard as it looks in this case.

When you define an array:

char myString[] = {'H' , 'e', 'l', 'l', 'o', \0};

That's a null terminated array of char variables. It's got the null (a zero) on the end there to mark the end of the string.

Now array syntax is just another way of writing pointers. If you've used arrays then you've already used pointers and just didn't realize it. In this case, myString is really a pointer to the first element of the string, the 'H', and whatever number you put in the brackets when you use it gets you whichever letter out, like myString[4] is 'o'.

So you could create an array like that and fill it up with whatever you want and pass it to the function as a char*. Just write myString with no brackets behind it and that's a char* since myString is an array of char.

There's another syntax to pointers where the * makes more sense. If you wanted to change the H into a Y and make the word Yello, you could write:

char myString = {'H' , 'e', 'l', 'l', 'o', \0};

*myString = 'Y';  // change the H to a Y
*(myString +1) = 'a';// change the e into an a

The * "dereferences" the pointer. It says, instead of working on this pointer, I want to work on the thing it points to. And like I show there, you can add to the pointer. It's just a number after all, a memory address. Add 1 to it in this case means when you dereference it with the * you are getting the thing one past what's pointed at by myString.

Most of the time code that needs a char* is going to look something like this. Create a char array (the buffer) and then fill it with all the strings you want, and then print it or send it or do whatever.

char buf[MESSAGE_LENGTH];

// lots of functions here, sprintf, strcat, strcpy, itoa, dtostrf.
// Go look those up.  You'll need them if you're going to 
// keep at this type of programming

someFunction(buf); // someFunction expects a char*.

And I would be remiss not to add, that for strings you can take a bit of a shortcut. Instead of the way I wrote out the array up there with all the letters in single quotes, you can use double quotes. The compiler will interpret anything in double quotes as a string of characters with a null at the end. So this would have been an equivalent definition for myString;

char* myString = "Hello";

That creates an array in memory holding "Hello" just like before and gives you a pointer to it in myString. It is exactly the same as what I wrote up there.

And of course since we're talking about pointers I'll mention the &. & get's the address of a variable. That's how you can tell a pointer what to point to.

int* p;
int someInt = 7;

p = &someInt;  // tells p to point to someInt 
                        //  No star because we're working on the pointer itself
*p = 8;            // now someInt is = 8 because p was pointing to it 
                       //  we used the * because we aren't changing p but the thing it is pointing to

Good.
@Delta_G, You must be drinking a nice glass of red wine tonight +1.

  char  myString[] = {'H' , 'e', 'l', 'l', 'o', '\0'};

  *myString = 'Y';  // change the H to a Y
  *(myString + 1) = 'a'; // change the e into an a

I'm seeing all that you wrote, but somehow it isn't "going in"...

client.publish(PubTopic,payload);

Ok, PubTopic is set earlier on.

It is "ArduinoTemp"
(set by:)

char* PubTopic = "ArduinoTemp";

So, reading it through my eyes, "PubToipc" and "payload" are the same kind/type of varaible.

So: I need to make payload with a char* command.

In the code I posted the "string" is constructed by a few of these kind of lines:

  Serial.print (dat [0], DEC); // display the humidity-bit integer;

So I go on and do this to make the longer string I want to put in payload.

  message = String(dat[0]) + '.' + String(dat[1]) + "    " + String(dat[2]) + '.' + String(dat[3]);

Ok, so that puts the string in the variable "message".

Looking at the only part I can see that then starts to do what I need is this line:

char* myString = "Hello";

So I try:

  String message;
  message = String(dat[0]) + '.' + String(dat[1]) + "    " + String(dat[2]) + '.' + String(dat[3]);
  Serial.println("========");
  Serial.println(message);
  char* payload = message;  //  line 156
  
  
  
  client.publish(PubTopic,payload);

and I get this:

Temp_Humidity_Arduino.ino:156:19: error: cannot convert ‘String’ to ‘char*’ in initialization

I am going in circles.

There is something I am missing.

Yeah. Forget you ever heard of String and pretend that you’ve never heard of putting strings together with a +. It’s just going to cause issues and maybe even program crashes even if you get it right. In that long post I have you an example that listed a lot of functions for you to look up. Did you google those? They show how to build a String in an array.