problems with INT values i believe (FIXED)

Hi All,

sorry, a bit of help please.

I am sure I am just getting mixed up with using my INT's on the ackData variable.

I have two codes master and slave for polling data from door sensors.

I have included the full codes here

the issue I have is that what is being sent from the slave is not what is being shown as the output from theaster, and I know it will be something simple!

Master code:

// MultiTxAckPayload - the master or the transmitter
//   works with two Arduinos as slaves
//     each slave should the SimpleRxAckPayload program
//       one with the adress {'R','x','A','A','A'}
//         and the other with {'R','x','A','A','B'}

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>


#define CE_PIN   D7
#define CSN_PIN D8

const byte numSlaves = 3;
const byte slaveAddress[numSlaves][5] = {
  // each slave needs a different address
  {'R', 'x', 'A', 'A', 'A'},
  {'R', 'x', 'A', 'A', 'B'},
  {'R', 'x', 'A', 'A', 'C'}
};

RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

//~ char dataToSend[10] = "Message 0";
char dataToSend[10] = "ToSlvN  0";
char txNum = '0';
int ackData[3] = {0,0,0}; // to hold the two values coming from the slave
bool newData = false;

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 1000; // send once per second

const char* ssid = "xxxxxxxx";
const char* password = "xxxxxxxx";
const char* mqtt_server = "xxxxxxxxx";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic", "hello world");
      // ... and resubscribe
      client.subscribe("inTopic");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

//===============

void setup() {

  Serial.begin(115200);
  Serial.println(F("Source File = /mnt/SGT/SGT-Prog/Arduino/ForumDemos/nRF24Tutorial/MultiTxAckPayload.ino "));
  Serial.println("SimpleTxAckPayload Starting");
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  radio.begin();
  radio.setDataRate( RF24_250KBPS );

  radio.enableAckPayload();

  radio.setRetries(3, 5); // delay, count
  // radio.openWritingPipe(slaveAddress); -- moved to loop()
}

//=============

void loop() {
    if (!client.connected()) {
    reconnect();
  }
  client.loop();
  currentMillis = millis();
  if (currentMillis - prevMillis >= txIntervalMillis) {
    send();
  }

  // showData(); -- moved into send()
}

//================

void send() {

  // call each slave in turn
  for (byte n = 0; n < numSlaves; n++) {

    // open the writing pipe with the address of a slave
    radio.openWritingPipe(slaveAddress[n]);

    // include the slave number in the message
    dataToSend[5] = n + '0';

    bool rslt;
    rslt = radio.write( &dataToSend, sizeof(dataToSend) );
    // Always use sizeof() as it gives the size as the number of bytes.
    // For example if dataToSend was an int sizeof() would correctly return 2

    Serial.print("  ========  For Slave ");
    Serial.print(n);
    Serial.println("  ========");
    Serial.print("  Data Sent ");
    Serial.print(dataToSend);
    if (rslt) {
      if ( radio.isAckPayloadAvailable() ) {
        radio.read(&ackData, sizeof(ackData));
        newData = true;
      }
      else {
        Serial.println("  Acknowledge but no data ");
      }
      updateMessage();
    }
    else {
      Serial.println("  Tx failed");
    }
    showData(n);
    Serial.print("\n");
  }

  prevMillis = millis();
}


//=================

void showData(byte n) {
  if (newData == true) {
    Serial.print("  Acknowledge data ");
    Serial.print(ackData[0]);
    Serial.print(", ");
    Serial.print(ackData[1]);
    Serial.print(", ");
    Serial.print(ackData[2]);
    Serial.println();
    newData = false;

    if (n == 0) {
      snprintf (msg, 50, "%ld", ackData[0]);
      client.publish("sensor/window1", msg);
      snprintf (msg, 50, "%ld", ackData[1]);
      client.publish("sensor/window2", msg);
    }
    
  }
}

//================

void updateMessage() {
  // so you can see that new data is being sent
  txNum += 1;
  if (txNum > '9') {
    txNum = '0';
  }
  dataToSend[8] = txNum;
}

slave Code

// SimpleRxAckPayload- the slave or the receiver

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define CE_PIN   7
#define CSN_PIN 8

#define sensor1 2 
#define sensor2 3 
#define sensor3 4 

const byte thisSlaveAddress[5] = {'R', 'x', 'A', 'A', 'A'};

RF24 radio(CE_PIN, CSN_PIN);

char dataReceived[10]; // this must match dataToSend in the TX
int ackData[3] = {0,0,0}; // the two values to be sent to the master
bool newData = false;

//==============

void setup() {

    Serial.begin(115200);

    Serial.println("SimpleRxAckPayload Starting");
    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.openReadingPipe(1, thisSlaveAddress);

    radio.enableAckPayload();
    
    radio.startListening();

    radio.writeAckPayload(1, &ackData, sizeof(ackData)); // pre-load data

    pinMode(sensor1, INPUT_PULLUP);
    pinMode(sensor2, INPUT_PULLUP);
    pinMode(sensor3, INPUT_PULLUP);
    
}

//==========

void loop() {
    getData();
    showData();
}

//============

void getData() {
    if ( radio.available() ) {
        radio.read( &dataReceived, sizeof(dataReceived) );
        updateReplyData();
        newData = true;
    }
}

//================

void showData() {
    if (newData == true) {
        Serial.print("Data received ");
        Serial.println(dataReceived);
        Serial.print(" ackPayload sent ");
        Serial.print(ackData[0]);
        Serial.print(", ");
        Serial.print(ackData[1]);
        Serial.print(", ");
        Serial.println(ackData[2]);
        
        newData = false;
        newData = false;
    }
}

//================

void updateReplyData() {
  if (digitalRead(sensor1) == LOW){
    ackData[0]=1;
  } else {
    ackData[0]=0;
  }
    if (digitalRead(sensor2) == LOW){
    ackData[1]=1;
  } else {
    ackData[1]=0;
  }
    if (digitalRead(sensor3) == LOW){
    ackData[2]=1;
  } else {
    ackData[2]=0;
  }

    radio.writeAckPayload(1, &ackData, sizeof(ackData)); // load the payload for the next time
}
    // open the writing pipe with the address of a slave
    radio.openWritingPipe(slaveAddress[n]);

slaveAddress is declared as a 2 dimension array.

Yes because it is a 2d array.

So why do you use it as a single dimensional array?

post #17 gives the set up of the master slave. I have changed this at all, and works fine.

Transmission works fine

The problem I am having is the ackData int which does not seem to work.

If you this this is linked to the server array (slaveaddress) could you please explain why.

Many thanks

The problem I am having is the ackData int which does not seem to work.

You think you are sending some data, but you haven't showed us what you think you are sending.

You think you are receiving some data, but you haven't showed us what you think you are receiving.

And, yet you think we can tell you why the data you receive is not what you send. Why do you think that?

PaulS:
You think you are sending some data, but you haven't showed us what you think you are sending.

You think you are receiving some data, but you haven't showed us what you think you are receiving.

And, yet you think we can tell you why the data you receive is not what you send. Why do you think that?

That is shown I the table in the first post. Sent is what is sent from the slave and shown via serial.print via the slaves com port. Recieved is what is output via serial.print in the masters com port.

I thought it was clear in the table. But I guess not..

int ackData[3] = {0,0,0}; // the two values to be sent to the master

Take your shoes off if you need to. Count the number of initializers. Look at the value in the square brackets. Then, look at the useless comment. If you are going to add useless comments, there is nothing worse you can do than provide useless comments that are wrong.

Why, if you want to send 0 or 1 as the ack values do you need to store the values in an int array? Perhaps you really need a long array, or a long long array.

    radio.startListening();

    radio.writeAckPayload(1, &ackData, sizeof(ackData)); // pre-load data

Do you have a clue when you should send the ack(nowledge) payload? Why are you acknowledging having received good data when you haven't received ANY data?

Ok, the useless comment is from the original code, apologies for not changing 2 to 3.

The idea is that the master sends a message to each of the slaves in turn, the acklodgement sent back is the data from the slave.

This is apparently the way to do it to avoid switching modes.

It is just to show the state of up to 3 switches, open (0) or closed (1) this is the "processed" at the master and mqtt states shared.

The idea is that the master sends a message to each of the slaves in turn, the acklodgement sent back is the data from the slave.

Suppose that you have a friend named Joe. You (master) say "Hey, Joe (slave). What time is it?".

EXACTLY when should Joe respond? As soon as he starts listening? That's what your code does now.

Or, should he respond only after he determines that you have asked him for some specific information?

You still haven't described why you are using an int array, using 6 bytes, to send 3 bits of information.

PaulS:
Suppose that you have a friend named Joe. You (master) say "Hey, Joe (slave). What time is it?".

EXACTLY when should Joe respond? As soon as he starts listening? That's what your code does now.

Or, should he respond only after he determines that you have asked him for some specific information?

Exactly when it received the request as set up.

You still haven't described why you are using an int array, using 6 bytes, to send 3 bits of information.

Only because that was the way it was set up in the tutorial post.

Exactly when it received the request as set up.

So, why DO you send an ACK payload as soon as you start listening?

Only because that was the way it was set up in the tutorial post.

So, if the tutorial had been written to send floats, you would have tried to stuff your 3 bits in a 12 byte array of floats. Why? The idea is that you send the proper type, and amount of data, for YOUR purposes, not someone else's purposes.

To be clear I am still learning, I am trying my best to teach myself.

I found a code that did exactly what I needed as a tutorial so I used it and it worked exactly as it should.

All I changed was instead of sending two random numbers back, it sent back three values.

In making that change it stopped working. It no longer showed the same data. Previous: received=sent. Now received != sent but does change consistently depending on pins selected.

I assumed it was because of the way I was setting the value.

I am using the int as I knew it worked. If it had worked with a float, yes I would have kept it it as a float. At the moment I dont know enough to change items based on memory usage. At the moment if it works it works and it does what I need.

As my knowledge progresses then yes I will develop this knowledge. But at the moment I just need to know why sent!=received.

Your conversation between the master and the slave is going like this:
You: Hey, Joe, wake up.
Joe: It's 3:40 AM
You: Hey, Joe, what time is it?
Joe: It's 4:18 PM

After Joe replies that it is 4:18 PM, you start paying attention to his replies. His first reply, which is completely unintelligent, is that it is 3:40 AM, which is nowhere near the time you expect, so you assume that the problem is that Joe is a doofus.

Well, I've got a clue for you. Joe is right. He isn't the doofus. You are, for writing code that acknowledges data from the master BEFORE the master has sent anything.

STOP DOING THAT. Get rid of that first call to writeAckPayload() - the one right after you start listening. ONLY send an ack payload AFTER you have gotten something from the master.

Thank you so much for the personal insult when I have asked for help. Massively appreciated when I explained I am new to this.

Forget it. In 30 years of teaching I have never felt the need to throw insults about, but if it makes you feel better good for you.

JonMiles:
Thank you so much for the personal insult when I have asked for help. Massively appreciated when I explained I am new to this.

Forget it. In 30 years of teaching I have never felt the need to throw insults about, but if it makes you feel better good for you.

The advice he is giving you is sound. I understand that the tone might be a bit grating, but you need to expect that from a forum filled with developers. Please put your thick skin on, try not to take things personal.

Personal insults by there very nature are personal.

Great, his advice my be sound, but did not answer the original question.

That is why is the repeated data incorrectly reported, not the first but all.

If this is beyond him then surely better to step aside and allow someone more knowledgeable to take up the batten.

That is why is the repeated data incorrectly reported, not the first but all.

When you put garbage in the stream up front, and read the same number of bytes each time, none of the data is ever going to be correct.

Even though it is reset after each one cycle.

If I understand correctly it's the writeAckPayload() in the set up of the slave code that is erroneous.

On the master, this ackData is replaced each time it polls a new slave, if I am reading the code correctly?

If so, why is it only on one of the slaves it does this, the others at report 0,0,0 each time?

Remember the earlier conversion between you and Joe? The first response from Joe contains incorrect data, but, if you assume that the data is good, you'll question the integrity of Joe's data. So, you ask him the time again, and he reports the correct time, but you then hear is previous response. So, you think the data is wrong again. So, you ask for the third time, and hear the second proper response, and again conclude that he's wrong.

After a while, you ask for the 4th time, and hear his 3rd response...

Can't you see that you MUST stop the slave from blurting out garbage as soon as it starts listening?