nrf24 autoack slaves with same address

Whandall:
To help you design a good system, I have to know the whole picture,
described in words as I layed out in my last post.

The data that should be broadcasted needs a description with the same level of detail.

All nodes, all commands, all announcements with ranges for any value.

I understand the Timer structure now

  if (millis() - sometime >= 1500){
     Timers[1].onTime = 12;
  Timers[2].onTime = 12;
  Serial.print("Timer 1 on time is ");
  Serial.println(Timers[1].onTime);
    Serial.print("Timer 2 on time is ");
  Serial.println(Timers[2].onTime);
  sometime = millis();
  }

the dose controller simply broadcasts its counter and for congestion sakes it only needs to broadcast the doseUp and doseDown counter on the multicast pipe about 1 time a second. How ever they need to only receive 3 commands that require ack, doseUpStart command and doseDownStart command, setDoseTime in milliseconds to set how long to turn the pump on for. There will be 4 dose controller total in the whole system i have 2 built and running right now. The ph monitor's is the most simple. The 2 ph module's simply broadcast the 2 float phvalue's on the multicast pipe 1 time every second

Better put a disp() function inside aTimer, then you only have to write timer print code once.

I have a basic understanding of setDoseTime (units? range?),
but doseUpStart and doseDownStart confuse me, what do these words mean?

Whandall:
Better put a disp() function inside aTimer, then you only have to write timer print code once.

I have a basic understanding of setDoseTime (units? range?),
but doseUpStart and doseDownStart confuse me, what do these words mean?

Since i dont want to have to send a second command to stop the dose pump i have the pump motors controlled with millis() and state changes. example,

 if (incommingCommand == doseUpStart){ 
someTime = millis();
DoseUpstate = true;
}

if (doseUpstate){
//turn on pump
if (millis() - someTime >= doseUpOnTime){
doseUpstate = false;
//turnOff pump
someTime = millis();
}

im going to try this "Better put a disp() function inside aTimer, then you only have to write timer print code once."

enum TiStates {
  tiEnabled = 0x80,
  tiRunning = 0x40,
  tiOnValue = 0x20,
  tiUpdated = 0x10,
};

void charOrDot(bool select, char display) {
  Serial.write(select ? display : '.');
}

struct aTimer {
  byte status;
  uint16_t onTime;
  uint16_t offTime;
  aTimer(uint16_t iOn, uint16_t iOff) : status(0), onTime(iOn), offTime(iOff) {}
  aTimer() : status(0), onTime(0), offTime(0) {}
  void disp() {
    Serial.write(' ');
    charOrDot(status & tiEnabled, 'E');
    charOrDot(status & tiRunning, 'R');
    charOrDot(status & tiOnValue, 'O');
    charOrDot(status & tiUpdated, 'U');
    Serial.print(F(" on "));
    Serial.print(onTime);
    Serial.print(F(", off "));
    Serial.println(offTime);
  }
};

struct TimerInfos {
  aTimer Timers[4];
  TimerInfos () : Timers{  aTimer(111, 222), aTimer(333, 444), aTimer(555, 666), aTimer(777, 888)  } {}
  void disp() {
    for (byte i = 0; i < 4; i++) {
      Serial.print(i + 1);
      Timers[i].disp();
    }
  }
} test;

void setup() {
  Serial.begin(250000);
  for (byte i = 0; i < 4; i++) {
    test.Timers[i].status |= 0x80 >> i;
  }
  test.disp();
}
void loop() {}
1 E... on 111, off 222
2 .R.. on 333, off 444
3 ..O. on 555, off 666
4 ...U on 777, off 888

Whandall:

enum TiStates {

tiEnabled = 0x80,
  tiRunning = 0x40,
  tiOnValue = 0x20,
  tiUpdated = 0x10,
};

void charOrDot(bool select, char display) {
  Serial.write(select ? display : '.');
}

struct aTimer {
  byte status;
  uint16_t onTime;
  uint16_t offTime;
  aTimer(uint16_t iOn, uint16_t iOff) : status(0), onTime(iOn), offTime(iOff) {}
  aTimer() : status(0), onTime(0), offTime(0) {}
  void disp() {
    Serial.write(' ');
    charOrDot(status & tiEnabled, 'E');
    charOrDot(status & tiRunning, 'R');
    charOrDot(status & tiOnValue, 'O');
    charOrDot(status & tiUpdated, 'U');
    Serial.print(F(" on "));
    Serial.print(onTime);
    Serial.print(F(", off "));
    Serial.println(offTime);
  }
};

struct TimerInfos {
  aTimer Timers[4];
  TimerInfos () : Timers{  aTimer(111, 222), aTimer(333, 444), aTimer(555, 666), aTimer(777, 888)  } {}
  void disp() {
    for (byte i = 0; i < 4; i++) {
      Serial.print(i + 1);
      Timers[i].disp();
    }
  }
} test;

void setup() {
  Serial.begin(250000);
  for (byte i = 0; i < 4; i++) {
    test.Timers[i].status |= 0x80 >> i;
  }
  test.disp();
}
void loop() {}




1 E... on 111, off 222
2 .R.. on 333, off 444
3 ..O. on 555, off 666
4 ...U on 777, off 888

Wow.
what is the meaning of the ? here "Serial.write(select ? display : '.');" I think i may have asked this many times but, Your invoking charOrDot handing it variable "status" and the address of tiEnabled. But the what is the 'E' for? "charOrDot(status & tiEnabled, 'E');"

i did run the code, the output is,

1 E... on 111, off 222
2 .R.. on 333, off 444
3 ..O. on 555, off 666
4 ...U on 777, off 888

is this bitwise & like status and the hex data of tiEnabled, or address of

You should start learning C++, did I mention that before?

Use the tutorial I linked, I will not read documentation to you.

Whandall:
You should start learning C++, did I mention that before?

Use the tutorial I linked, I will not read documentation to you.

C++ Syntax Reference - Ternary Operator - Cprogramming.com

I understand how they express it here "int five_divided_by_x = ( x != 0 ? 5 / x : 0 );" Forgive me but in your serial statement did you mean Serial.write?

the whole function,

void charOrDot(bool select, char display) {
Serial.write(select ? display : '.');
}

what value am i comparing? which brings me to this part,

charOrDot(status & tiEnabled, 'E');

what does what does status actually have, can you please tell me exactly what happens there in order.

Can you tell me the meaning of the hex values chooses here?
tiEnabled = 0x80,
tiRunning = 0x50,
tiOnValue = 0x20,
tiUpdated = 0x10,

This is going way over my head, I know what the for loop is. It all goes down hill here,

.status |= 0x80 >> i;

I understand that >> is a right shift operator which i still have no idea what its doing.

Heres another bitwise operator thats making things harder for me to understand,

status |= 0x80 // status = status OR 0x80 this must be wrong.

Even after reading about the operator its not making any more sense to me.

Why exactly did you pick the values you did for,
tiEnabled = 0x80,
tiRunning = 0x40,
tiOnValue = 0x20,
tiUpdated = 0x10,

I think if i understood exactly what those two pieces of code were doing i would pretty much understand the rest of the program.

EDIT: I'm learning more about the bitshift operators This,
enum TiStates {
tiEnabled = 0x80,
tiRunning = 0x40,
tiOnValue = 0x20,
tiUpdated = 0x10,
};
is the same as,
enum TiStates {
tiEnabled = 128,
tiRunning = 64,
tiOnValue = 32,
tiUpdated = 16,
};

I'm strating to understand more but |= is a bit confusing.
test.Timers*.status |= 0x80 >> i; //right bitshift 0x80 the value of i*

status |= 0x80 // status = status OR 0x80 this must be wrong.

Why do you think so?

For the demo disp I wanted to have a single bit set in each of the for elements.

Whandall:
Why do you think so?

For the demo disp I wanted to have a single bit set in each of the for elements.

Operators in C and C++ - Wikipedia

So its not wrong. For some reason i cant picture this doing anything but division and changing "status" to the result of the right bit shift operator and "i",

test.Timers*.status |= 0x80 >> i; //right bitshift 0x80 by value of i*

notsolowki:
For some reason i cant picture this doing anything but division and changing "status" to the result of the right bit shift operator,

test.Timers_.status |= 0x80 >> i; //right bitshift 0x80 by value of i_
[/quote]
That is not what is happening, you overlooked the '|' in the assignment operator.
(ok, the results are the same, but only because all the status fields are zero to begin with)
Read the documentation I link.

Whandall:
That is not what is happening, you overlooked the '|' in the assignment operator.
(ok, the results are the same, but only because all the status fields are zero to begin with)

Read the documentation I link.

I read there and it says "a or_eq b"

So i thought that means in this program,

Timer.[1].status = status OR status = 0x80 / 1
Timer.[2].status = status OR status = 0x80 / 2
Timer.[3].status = status OR status = 0x80 / 3
Timer.[4].status = status OR status = 0x80 / 4

this isn't right? I understand Timers number is changing too

No, you got the division values wrong.

Timer[0].status = Timer[0].status OR 0x80 / 1;
Timer[1].status = Timer[1].status OR 0x80 / 2;
Timer[2].status = Timer[2].status OR 0x80 / 4;
Timer[3].status = Timer[3].status OR 0x80 / 8;

Whandall:
No, you got the division values wrong.

status = status OR status = 0x80 / 1;

status = status OR status = 0x80 / 2;
status = status OR status = 0x80 / 4;
status = status OR status = 0x80 / 8;

Yes thank you for correcting me. Is this correct,

charOrDot(status & tiEnabled, 'E');

this is invoking a fuction "charOrDot" with the result of "status |= 0x80" and tiEnabled" what is the 'E' for. why do i not get this. select will return true if status has a value.

Basically the function is:

if the enable bit is set, the character to display is 'E', if not it's a '.'.

What single character would you pick to show an enabled timer?

Whandall:
Basically the function is:

if the enable bit is set, the character to display is 'E', if not it's a '.'.

And by enable bit were talking about status having a value other than 0 to make select return true that way it stops printing '.' and prints the char 'E' handed ove to display? Do i understand this correctly now?

More or less, yes.

So how am i going to add a command to TiStates,

enum TiStates {
tiDisabled = 0x160,
tiEnabled = 0x80,
tiRunning = 0x40,
tiOnValue = 0x20,
tiUpdated = 0x10,
};

I would like to add a state identifier for timerDisabled and then modify it.
atleast i kind of know how to use the structure now

unsigned long someTime = 0;
int state = 0;

enum TiStates {
  tiDisabled = 0x160,
  tiEnabled = 0x80,
  tiRunning = 0x40,
  tiOnValue = 0x20,
  tiUpdated = 0x10,
};

void charOrDot(bool select, char display) {
  Serial.print(select ? display : '.'); // if there is no char in display then print a '.'
}

struct aTimer {
  byte status;
  uint16_t onTime;
  uint16_t offTime;
  aTimer(uint16_t iOn, uint16_t iOff) : status(0), onTime(iOn), offTime(iOff) {}
  aTimer() : status(0), onTime(0), offTime(0) {}
  void disp() {
    Serial.write(' ');
    charOrDot(status & tiEnabled, 'E');
    //charOrDot(status & tiDisabled, 'D');
    charOrDot(status & tiRunning, 'R');
    charOrDot(status & tiOnValue, 'O');
    charOrDot(status & tiUpdated, 'U');
    Serial.print(F(" on "));
    Serial.print(onTime);
    Serial.print(F(", off "));
    Serial.println(offTime);
  }
};

struct TimerInfos {
  aTimer Timers[4];
  TimerInfos () : Timers{  aTimer(111, 222), aTimer(333, 444), aTimer(555, 666), aTimer(777, 888)  } {}
  void disp() {
    for (byte i = 0; i < 4; i++) {
      Serial.print(i + 1);
      Timers[i].disp();
    }
  }
} test;




void setup() {
  Serial.begin(57600);
  for (byte i = 0; i < 4; i++) {
    test.Timers[i].status |= 0x80 >> i;  //right bitshift 0x80 the value of i
  }
  test.disp();

}

void loop() {
  if (millis() - someTime >= 1000) {
    test.Timers[1].onTime = 1;
    test.Timers[1].offTime = 1;
    if (state == 0) {
      test.disp();
      state = 1;
    }
    if (millis() - someTime >= 2000) {
      test.Timers[1].onTime = 2;
      test.Timers[1].offTime = 2;
      someTime = millis();
      state = 0;
      test.disp();
    }
  }

}

No, use single bits that fit in a byte for bit attributes.

And - if I may remind you - NOT enabled is disabled.
There is absolutely no reason to add a disabled value.

And it seems you think 0x160 would be two times 0x80. It is not.

Whandall:
No, use single bits that fit in a byte for bit attributes.

And - if I may remind you - NOT enabled is disabled.
There is absolutely no reason to add a disabled value.

And it seems you think 0x160 would be two times 0x80. It is not.

I have the receive code ready to accept incoming messages on its personal address with ack. I'm trying to imagine how i'm going to send something to it from the master. You think i should just use a string? How am i going to sort the timer values sent to the slave from a specific position in a string?

#include <RF24.h>

const byte pinCE = 9;
const byte pinCSN = 10;

const byte functionalAddress[] = "*-com"; //no ack address
const byte personalAddress[] = "P-com"; //auto ack enabled for this address
byte listenerAddress[] = "?-com";

unsigned long someTime = 0;
int state = 0;

enum TiStates {
  tiEnabled = 0x80, //timer enabled bit
  tiRunning = 0x40,
  tiOnValue = 0x20,
  tiUpdated = 0x10,
};

void charOrDot(bool select, char display) {
  Serial.print(select ? display : '.'); // if select true display that otherwise print '.'
}

struct aTimer {
  byte status;
  uint16_t onTime;
  uint16_t offTime;
  aTimer(uint16_t iOn, uint16_t iOff) : status(0), onTime(iOn), offTime(iOff) {} //constructor
  aTimer() : status(0), onTime(0), offTime(0) {}
  void disp() {
    Serial.write(' ');
    charOrDot(status & tiEnabled, 'E');
    charOrDot(status & tiRunning, 'R');
    charOrDot(status & tiOnValue, 'O');
    charOrDot(status & tiUpdated, 'U');
    Serial.print(F(" on "));
    Serial.print(onTime);
    Serial.print(F(", off "));
    Serial.println(offTime);
  }
};

struct TimerInfos {
  aTimer Timers[4];
  TimerInfos () : Timers{  aTimer(111, 222), aTimer(333, 444), aTimer(555, 666), aTimer(777, 888)  } {}
  void disp() {
    for (byte i = 0; i < 4; i++) {
      Serial.print(i + 1);
      Timers[i].disp();
    }
  }
} test;




byte incomingData[32];
RF24 radio(pinCE, pinCSN);

void setup() {
  Serial.begin(57600);
  radio.begin();
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_MAX);
  radio.setAutoAck(true);
  radio.enableDynamicPayloads();
  radio.setRetries(3, 15);
  radio.openReadingPipe(1, personalAddress);
  radio.startListening();
//  for (byte i = 0; i < 4; i++) {
//    test.Timers[i].status |= 0x80 >> i;  //right bitshift 0x80 the value of i
//  }
//  test.disp();

}

void loop() {
 
  if (millis() - someTime >= 1000) {
    test.Timers[1].onTime = 1;
    test.Timers[1].offTime = 1;
    if (state == 0) {
      test.disp();
      state = 1;
    }
    if (millis() - someTime >= 2000) {
      test.Timers[1].onTime = 2;
      test.Timers[1].offTime = 2;
      someTime = millis();
      state = 0;
      test.disp();
    }
  }
    if (radio.available()) {
    byte len = radio.getDynamicPayloadSize(); //get incoming data payload size
    radio.read( &incomingData, len); //write memory address into incomingdata and the length?
  }

}

EDIT, i had to change some of the code comments