nrf24 autoack slaves with same address

Yes.

You could use the free pipes to listen to nodes using ack without them noticing it.

I did not make it a command, because I would have to close all so used pipes in setup
for the next restart, as the NRF24 only really resets, if it is power cycled.

notsolowki:
Thats is just the original code i have not tried to adapt it to AllInOne

Read the messages I wrote in you absence, I tried to make things clearer to you.

Your addition of a command ("j3") does not really help in implementing/enforcing an already existing command.
It does not sanity check user input and will fail and possibly hang the whole system
if you enter a value above 3 or below 0.

im trying to make this compile its not done yet but its throwing a compiler error about pH.process(); "expected unqualified-id before '.' token"

AllInOne2.ino (9.92 KB)

packetDefinitions.h (21.9 KB)

notsolowki:
im trying to make this compile its not done yet but its throwing a compiler error about pH.process(); "expected unqualified-id before '.' token"

eDIT: I figured it out

I will try that again. here is what i have,

struct pH {
  int phreadstate;
  unsigned long phRefreshMarker = 0;
  unsigned long phSendDelay = 0;
  float pHValues[2];
  int buf[64], temp;
  int buf2[64], temp2;
  unsigned long int pH1avgValue;
  unsigned long int pH2avgValue;
  byte phAnalogPins[2];
  pH(byte from, byte pin1, byte pin2) : pH1avgValue(0), pH2avgValue(0), phAnalogPins{pin1, pin2},pHValues{5.89, 5.89}, phreadstate(1) {}
  void process() {
    if (millis() - phRefreshMarker > 850) {
      if (phreadstate == 1) {
        for (int i = 0; i < 60; i++)  {
          buf[i] = analogRead(phAnalogPins[1]);
          if (i >= 59) {
            phreadstate = 2;
          }
        }
      }
      if (phreadstate == 2) {
        for (int i = 0; i < 60; i++)  {
          buf2[i] = analogRead(phAnalogPins[2]); 
          if (i >= 59) {
            phreadstate = 1;
          }
        }
      }
         pH1avgValue = 0;
    for (int i = 0; i < 60; i++){
      pH1avgValue += buf[i];
  }
    float pHVol = (float)pH1avgValue * 5.0 / 1024 / 60;
    pHValues[1] = -5.7 * pHVol + 24.4;
    pH2avgValue  = 0;
    for (int i = 0; i < 60; i++){
      pH2avgValue  += buf2[i]; 
    }
    float pHVol2 = (float)pH2avgValue  * 5.0 / 1024 / 60;
    pHValues[2] = -5.7 * pHVol2 + 24.4;
    phRefreshMarker = millis();
    }
    if (millis() - phSendDelay > 100) {
      writeTo('*', pHValues, sizeof(pHValues), true);
      phSendDelay = millis();
    }
  }
};

There is no Hdr but there should be one,
packet and manager are one object but should not be,
the code is copy and paste (instead using two channels),
I consider 128 analog reads in row blocking,
the average buffers are static and as far as I can see duplicate (not used at the same time).

At least you are moving in the right direction, look at the structure of the other objects.

Hdr - data - managment data. The Hdr followed by the data allows to collect actions on a packet
or the manipulation of the data object, which supposedly is the real state.
The process level is separate to allow data objects to be moved around isolated in a simple way.

Now my cat does not allow me to continue typing. :wink:

i am confused about what to do for the second timer in the control panel code, do u just duplicate TimerInfos?

notsolowki:
i am confused about what to do for the second timer in the control panel code, do u just duplicate TimerInfos?

I don't have a console application that has a second Timer.

You are confused, because you don't read or remember what I write.

Whandall:
I see a lot of confusion (especially in regard to the flags) on your side.

You could make all the flags bool variables (if that helps you imagination pretend they are), but that

  • would take 8 times more space
  • would not allow to manipulate some or all of them at once
    To alleviate the pain remembering all the numeric values, enums are handy.

Some of the bools are control (enable), some are state (running), some are pure volatile state (updated).
We misuse the writing of running to signal an "abort and start this", so it is interpreted differently
if sensed as an input.

I bet updated is useful in the console to control necessary screen updates,
in the current implementation on a timer granularity.

On the timer announce you could see a usage for updated if you clear the flags after announcment
with seq.clrUpdated();. Note that all attribute of the base class are also available in the child class.
So as Sequencer is a TimerInfo, it has all TimerInfos functions and data fields.

Is there suppose to be an update flag when i set a new time?

in the control panel code i check for timer.status == tiUpdated) but for some reason when i change the timer that flag is not true. instead that statement becomes true when i disabled a timer? heres the timer code

   bool handleCommand(const char* buffer) {
      char* behind = nullptr;
      uint32_t value = 0;
      byte tIndex = 0;
      buffer = skipBlanks(buffer);
      switch (*buffer) {
        case 0:
        case '?':
          disp();
          break;
        case 'c':
          clrUpdated();
          break;
        case 's':
          clrAllFlags(tiRunning);
          break;
        case '0'...'3':
          tIndex = *buffer - '0';
          buffer = skipBlanks(buffer + 1);
          switch (*buffer) {
            case '0'...'9':
              value = strtoul(buffer, &behind, 0);
              if (value & 0xFFFF0000) {
                return false;
              }
              setOnTime(tIndex, value);
                setFlags(tIndex, tiUpdated);
              Serial.println("hi");
              behind = (char*)skipBlanks(behind);
              if (*behind == ',') {
                value = strtoul(behind + 1, &behind, 0);
                if (value & 0xFFFF0000) {
                  return false;
                }
                setOffTime(tIndex, value);
                  setFlags(tIndex, tiUpdated);
                     
              }
              break;
            case 'e':
              setFlags(tIndex, tiEnabled);
              break;
            case 'd':
              clrFlags(tIndex, tiEnabled);
              break;
            case 'g':
              setFlags(tIndex, tiRunning);
              break;
            default:
              return false;
          }
          break;
        default:
          return false;
      }
      return true;
    }
  protected:
    bool changedFlags(byte timerNumber, byte previous) {
      return adjustChangedFlag(timerNumber, (Timers[timerNumber].status ^ previous) & tiTriggerUpdate);
    }
    bool changedOn(byte timerNumber, uint16_t previous) {
      return adjustChangedFlag(timerNumber, Timers[timerNumber].onTime != previous);
    }
    bool changedOff(byte timerNumber, uint16_t previous) {
      return adjustChangedFlag(timerNumber, Timers[timerNumber].offTime != previous);
    }
    bool adjustChangedFlag(byte timerNumber, bool different) {
      if (different) {
        Timers[timerNumber].status |= tiUpdated;
        //} else {
        //  Timers[timerNumber].status &= ~tiUpdated;
      }
      return different;
    }
};

Basically what im trying to do is if the update flag is tiUpdated on the control panel then redrawn the timers on the screen. the problem is tiUpdated+enabled does not = tiUpdated. how do i do this?

You should have paid more attention to bit manipulation, what bits are, how they are tested
and the connection between a single bit and the value of its container.

.status == tiUpdated

does not test a bit, but a value.

This is getting really annoying. You just refuse to learn the needed basics. You rarely answer questions.

im just messing around but i changed the timer code to this,

    bool setOnTime(byte timerNumber, uint16_t value) {
      uint16_t previous = Timers[timerNumber].onTime;
      Timers[timerNumber].onTime = value;
      return true; // changedOn(timerNumber, previous);
    }
    bool setOffTime(byte timerNumber, uint16_t value) {
      uint16_t previous = Timers[timerNumber].offTime;
      Timers[timerNumber].offTime = value;
      return true; //changedOff(timerNumber, previous);
    }

on the control panel i did this,

void lcdRefresh() {
  if (zone == 1) {
    if ( seq.Timers[0].onTime != seq.prevTimersTime[0].onTime ) {
      Serial.println("updated");
      lcddelay = millis();
      myGLCD.setTextSize(1);
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 1 On Time: ", 5, 208);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRect (100, 207, 158, 215);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[0].onTime, 100, 208);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[0].onTime = seq.Timers[0].onTime ;
    if ( seq.Timers[0].offTime != seq.prevTimersTime[0].offTime ) {
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 1 Off Time: ", 5, 222);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRect (105, 220, 158, 228);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[0].offTime, 105, 222);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[0].offTime = seq.Timers[0].offTime ;

    if ( seq.Timers[1].onTime != seq.prevTimersTime[1].onTime ) {
      lcddelay = millis();
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 2 On Time: ", 5, 236);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRect (100, 235, 158, 243);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[1].onTime, 100, 236);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[1].onTime = seq.Timers[1].onTime ;
    if ( seq.Timers[1].offTime != seq.prevTimersTime[1].offTime ) {
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 2 Off Time: ", 5, 250);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRoundRect (105, 249, 158, 258);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[1].offTime, 105, 250);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[1].offTime = seq.Timers[1].offTime ;

    if ( seq.Timers[2].onTime != seq.prevTimersTime[2].onTime ) {
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 3 On Time: ", 5, 264);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRoundRect (100, 263, 158, 271);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[2].onTime, 100, 264);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[2].onTime = seq.Timers[2].onTime ;
    if ( seq.Timers[2].offTime != seq.prevTimersTime[2].offTime ) {
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 3 Off Time: ", 5, 278);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRoundRect (105, 277, 158, 285);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[2].offTime, 105, 278);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[2].offTime = seq.Timers[2].offTime ;
    if ( seq.Timers[3].onTime != seq.prevTimersTime[3].onTime ) {
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 4 On Time: ", 5, 292);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRoundRect (100, 290, 158, 298);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[3].onTime, 100, 292);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[3].onTime = seq.Timers[3].onTime ;
    if ( seq.Timers[3].offTime != seq.prevTimersTime[3].offTime ) {
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 4 Off Time: ", 5, 306);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRect (105, 305, 158, 316);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[3].offTime, 105, 306);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[3].offTime = seq.Timers[3].offTime ;
  }
}

I sort of understand bitwise i understand how bits are shifted. and how a byte can uqual up to 255 in decimal. how when you shift bitch your multiplying or dividing. i just still dont get how to use them.

let me know if you this this is a terrible way

Disabling functionality to reinvent it, using additional resources (a full object) in a different place, is a bad idea.

Whandall:
Disabling functionality to reinvent it, using additional resources (a full object) in a different place, is a bad idea.

can you shed some more light on this part and give me an example what im doing wrong?

this is my display loop i have so far. things are updating to the screen. the way i want but im not sure if im doing it right. i know for sure im probably not using the flags right. I'm not sure i ever will unless someones draws it with a crayon for me lol

void processTouch() {
    selectCalibration();
  if (readTouch) {
    tp = ts.getPoint();
    pinMode(XM, OUTPUT);
    pinMode(YP, OUTPUT);
    if (tp.z > touchMin && tp.z < touchMax) {
      Serial.println("p1");
      if (millis() - lcdDebounceWait >= lcdDebounce) {
              Serial.println("p2");
        if (!blockInput) {
          if (timerSet == 0) {
      Serial.println("p3");
            //            myGLCD.drawRoundRect(164, 205, 315, 230); //start
            //            myGLCD.fillRoundRect (164, 205, 315, 230);//start
            if (x > 164 && x < 315  && y > 205 && y < 230) { //dose 1 up button
              buttonBorder(164, 205, 315, 230 );
              Serial.println("hello");
              //  timerInfoResetdelay = millis() - 1010;
              zone ++;
              delay(200);
              if (zone == 2) {
                myGLCD.setTextSize(2);
                myGLCD.setColor(51, 255, 51);
                myGLCD.fillRoundRect (164, 205, 315, 230);//zone button
                myGLCD.setColor(0, 0, 0);
                myGLCD.print(" Zones 2/2", 171, 210); //timer
                myGLCD.setTextSize(1);
                myGLCD.fillRect (100, 207, 158, 215);
                myGLCD.fillRect (105, 220, 158, 228);
                myGLCD.fillRect (100, 235, 158, 243);
                myGLCD.fillRoundRect (105, 249, 158, 258);
                myGLCD.fillRoundRect (100, 263, 158, 271);
                myGLCD.fillRoundRect (105, 277, 158, 285);
                myGLCD.fillRoundRect (100, 290, 158, 298);
                myGLCD.fillRect (105, 305, 158, 316);
                myGLCD.setColor(255, 255, 255);
                myGLCD.setColor(138, 93, 59);
                myGLCD.printNumI(ti.Timers2[0].onTime, 100, 208);
                myGLCD.printNumI(ti.Timers2[0].offTime, 105, 222);
                myGLCD.printNumI(ti.Timers2[1].onTime, 100, 236);
                myGLCD.printNumI(ti.Timers2[1].offTime, 105, 250);
                myGLCD.printNumI(ti.Timers2[2].onTime, 100, 264);
                myGLCD.printNumI(ti.Timers2[2].offTime, 105, 278);
                myGLCD.printNumI(ti.Timers2[3].onTime, 100, 292);
                myGLCD.printNumI(ti.Timers2[3].offTime, 105, 306);
                myGLCD.setColor(255, 255, 255);
                myGLCD.setTextSize(2);
              }
              if (zone >= 3 ) {
                myGLCD.setTextSize(2);
                myGLCD.setColor(51, 255, 51);
                myGLCD.fillRoundRect (164, 205, 315, 230);//zone button
                myGLCD.setColor(0, 0, 0);
                myGLCD.print(" Zones 1/2", 171, 210); //timer3
                myGLCD.setTextSize(1);
                myGLCD.fillRect (100, 207, 158, 215);
                myGLCD.fillRect (105, 220, 158, 228);
                myGLCD.fillRect (100, 235, 158, 243);
                myGLCD.fillRoundRect (105, 249, 158, 258);
                myGLCD.fillRoundRect (100, 263, 158, 271);
                myGLCD.fillRoundRect (105, 277, 158, 285);
                myGLCD.fillRoundRect (100, 290, 158, 298);
                myGLCD.fillRect (105, 305, 158, 316);
                myGLCD.setColor(255, 255, 255);
                myGLCD.setColor(138, 93, 59);
                myGLCD.printNumI(seq.Timers[0].onTime, 100, 208);
                myGLCD.printNumI(seq.Timers[0].offTime, 105, 222);
                myGLCD.printNumI(seq.Timers[1].onTime, 100, 236);
                myGLCD.printNumI(seq.Timers[1].offTime, 105, 250);
                myGLCD.printNumI(seq.Timers[2].onTime, 100, 264);
                myGLCD.printNumI(seq.Timers[2].offTime, 105, 278);
                myGLCD.printNumI(seq.Timers[3].onTime, 100, 292);
                myGLCD.printNumI(seq.Timers[3].offTime, 105, 306);

                myGLCD.setColor(255, 255, 255);
                myGLCD.setTextSize(2);
                zone = 1;
              }
            }
          }
        }
      }
    }
      if (zone == 1) {
         if (seq.Timers[0].status ==tiEnabled){
          myGLCD.setTextSize(1);
          myGLCD.setColor(255, 255, 255);
          myGLCD.print("Enabled   ", 10, 470);
          myGLCD.setTextSize(2);
         }
        }
        if (seq.Timers[0].status ==0) {
          myGLCD.setTextSize(1);
          myGLCD.setColor(255, 255, 255);
          myGLCD.print("Disabled  ", 10, 470);
          myGLCD.setTextSize(2);
        }
        
//        if (timer1Status == 3) {
//          myGLCD.setTextSize(1);
//          myGLCD.setColor(255, 255, 255);
//          myGLCD.print("connection", 10, 470);
//          myGLCD.setTextSize(2);
//        }

        if (seq.Timers[1].status ==tiEnabled){
          myGLCD.setTextSize(1);
          myGLCD.setColor(255, 255, 255);
          myGLCD.print("Enabled   ", 90, 470);
          myGLCD.setTextSize(2);
        }
      if (seq.Timers[1].status ==0) {
          myGLCD.setTextSize(1);
          myGLCD.setColor(255, 255, 255);
          myGLCD.print("Disabled  ", 90, 470);
          myGLCD.setTextSize(2);
        }
//        if (timer2Status == 3) {
//          myGLCD.setTextSize(1);
//          myGLCD.setColor(255, 255, 255);
//          myGLCD.print("connection", 90, 470);
//          myGLCD.setTextSize(2);
//        }
        if (seq.Timers[2].status ==tiEnabled){
          myGLCD.setTextSize(1);
          myGLCD.setColor(255, 255, 255);
          myGLCD.print("Enabled   ", 169, 470);
          myGLCD.setTextSize(2);
        }
         if (seq.Timers[2].status ==0) {
          myGLCD.setTextSize(1);
          myGLCD.setColor(255, 255, 255);
          myGLCD.print("Disabled  ", 169, 470);
          myGLCD.setTextSize(2);
        }
//        if (timer3Status == 3) {
//          myGLCD.setTextSize(1);
//          myGLCD.setColor(255, 255, 255);
//          myGLCD.print("connection", 169, 470);
//          myGLCD.setTextSize(2);
//        }
        if (seq.Timers[3].status ==tiEnabled){
          myGLCD.setTextSize(1);
          myGLCD.setColor(255, 255, 255);
          myGLCD.print("Enabled   ", 249, 470);
          myGLCD.setTextSize(2);
        }
        if (seq.Timers[3].status ==0) {
          myGLCD.setTextSize(1);
          myGLCD.setColor(255, 255, 255);
          myGLCD.print("Disabled  ", 249, 470);
          myGLCD.setTextSize(2);
        }
//        if (timer4Status == 3) {
//          myGLCD.setTextSize(1);
//          myGLCD.setColor(255, 255, 255);
//          myGLCD.print("connection", 249, 470);
//          myGLCD.setTextSize(2);
//        }
  }

}

and heres pt2,

[code]
void lcdRefresh() {
  if (zone == 1) {
    if ( seq.Timers[0].onTime != seq.prevTimersTime[0].onTime ) {
      Serial.println("updated");
      lcddelay = millis();
      myGLCD.setTextSize(1);
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 1 On Time: ", 5, 208);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRect (100, 207, 158, 215);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[0].onTime, 100, 208);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[0].onTime = seq.Timers[0].onTime ;
    if ( seq.Timers[0].offTime != seq.prevTimersTime[0].offTime ) {
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 1 Off Time: ", 5, 222);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRect (105, 220, 158, 228);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[0].offTime, 105, 222);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[0].offTime = seq.Timers[0].offTime ;

    if ( seq.Timers[1].onTime != seq.prevTimersTime[1].onTime ) {
      lcddelay = millis();
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 2 On Time: ", 5, 236);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRect (100, 235, 158, 243);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[1].onTime, 100, 236);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[1].onTime = seq.Timers[1].onTime ;
    if ( seq.Timers[1].offTime != seq.prevTimersTime[1].offTime ) {
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 2 Off Time: ", 5, 250);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRoundRect (105, 249, 158, 258);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[1].offTime, 105, 250);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[1].offTime = seq.Timers[1].offTime ;

    if ( seq.Timers[2].onTime != seq.prevTimersTime[2].onTime ) {
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 3 On Time: ", 5, 264);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRoundRect (100, 263, 158, 271);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[2].onTime, 100, 264);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[2].onTime = seq.Timers[2].onTime ;
    if ( seq.Timers[2].offTime != seq.prevTimersTime[2].offTime ) {
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 3 Off Time: ", 5, 278);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRoundRect (105, 277, 158, 285);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[2].offTime, 105, 278);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[2].offTime = seq.Timers[2].offTime ;
    if ( seq.Timers[3].onTime != seq.prevTimersTime[3].onTime ) {
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 4 On Time: ", 5, 292);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRoundRect (100, 290, 158, 298);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[3].onTime, 100, 292);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[3].onTime = seq.Timers[3].onTime ;
    if ( seq.Timers[3].offTime != seq.prevTimersTime[3].offTime ) {
      myGLCD.setColor(138, 93, 59);
      myGLCD.print("Timer 4 Off Time: ", 5, 306);
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRect (105, 305, 158, 316);
      myGLCD.setColor(138, 93, 59);
      myGLCD.printNumI(seq.Timers[3].offTime, 105, 306);
      myGLCD.setColor(255, 255, 255);
    }
    seq.prevTimersTime[3].offTime = seq.Timers[3].offTime ;
  }
}

[/code]

will you please help me modify this state machine u built. i cannot for the life of me figure out how to jump to a different timer without screwing up all of the states. every time i try to modify it, it locks up. i been sitting here for 4 hours trying to do this without luck.

packetDefinitions.h (24.1 KB)

i need stop timer, jump to timer, and disable timer. your commands are not operating the flags right. i end up with all kinds of flags going at the same time and the timers quit . please show me this. t0d does not stop the timers t0s does not stop the timer, tc does not clear all the flags nor dos ts t0g does not start any timers just changes the run flag and dont do anything except that

byte jumpToTimer(int newState) {
digitalWrite(pins[currentStep], HIGH);
clrFlags(currentStep, tiOnPhase);
currentStep = newState;
setNewState(tsCheckLowPhase);
setNewState(tsCheckStep);
}
byte StopTimer() {
if (digitalRead(pins[currentStep]) == LOW) {
digitalWrite(pins[currentStep], HIGH);
clrFlags(currentStep, tiOnPhase);
setNewState(tsCheckLowPhase);
}

}

notsolowki:
can you shed some more light on this part and give me an example what im doing wrong?

You disable functionality

   return true; // changedOn(timerNumber, previous);
      return true; //changedOff(timerNumber, previous);

you reinvent it in a different place

 if ( seq.Timers[0].onTime != seq.prevTimersTime[0].onTime ) {
    seq.prevTimersTime[0].onTime = seq.Timers[0].onTime ;
    if ( seq.Timers[0].offTime != seq.prevTimersTime[0].offTime ) {
    seq.prevTimersTime[0].offTime = seq.Timers[0].offTime ;
    if ( seq.Timers[1].onTime != seq.prevTimersTime[1].onTime ) {
     seq.prevTimersTime[1].onTime = seq.Timers[1].onTime ;
    if ( seq.Timers[1].offTime != seq.prevTimersTime[1].offTime ) {
    seq.prevTimersTime[1].offTime = seq.Timers[1].offTime ;
    if ( seq.Timers[2].onTime != seq.prevTimersTime[2].onTime ) {
    seq.prevTimersTime[2].onTime = seq.Timers[2].onTime ;
    if ( seq.Timers[2].offTime != seq.prevTimersTime[2].offTime ) {
    seq.prevTimersTime[2].offTime = seq.Timers[2].offTime ;
    if ( seq.Timers[3].onTime != seq.prevTimersTime[3].onTime ) {
    seq.prevTimersTime[3].onTime = seq.Timers[3].onTime ;
    if ( seq.Timers[3].offTime != seq.prevTimersTime[3].offTime ) {
    seq.prevTimersTime[3].offTime = seq.Timers[3].offTime ;

and you are using additional resources seq.prevTimersTime.

notsolowki:
will you please help me modify this state machine u built. i cannot for the life of me figure out how to jump to a different timer without screwing up all of the states. every time i try to modify it, it locks up. i been sitting here for 4 hours trying to do this without luck.

Probably because you still do not understand how it is working.
There is no luck involved, it's only logic and knowledge.

I will not write your applications. The sketch I wrote does the regular work as specified,
there are only some obscure overrides that need to be handled.

Here you can see how I handle a go command on the not running dose pump,
if the other happens to execute if it gets set (2. term).
Here no action besides termination of the current state is needed
(just as it had finished (3. term), or its run flag was reset externaly (1. term)),
so I could integrate the handling in the if of the timeout.

        if (!(cPump->status & dpRunning) || aPump->executable() || (now - timeBase >= cPump->duration)) {

some context

void process() {
    if (runOk) {
      uint32_t now = millis();
      switch (smState) {
        case doPowerUp:
          timeBase = now;
          setNewState(doStartWait);
          break;
        case doStartWait:
          if (now - timeBase >= startupDelay) {
            setNewState(doSelectPump);
          }
          break;
        case doSelectPump:
          cPump = &up;
          aPump = &down;
          if (cPump->executable()) {
            cPin = pins[0];
            setNewState(doStartPump);
          } else {
            cPump = &down;
            aPump = &up;
            if (cPump->executable()) {
              cPin = pins[1];
              setNewState(doStartPump);
            }
          }
          break;
        case doStartPump:
          timeBase = now;
          timeProgress = now;
          cPump->percentDone = 0;
          progressDuration = cPump->duration / 100;
          progressInc = 1;
          if (progressDuration < 500) {
            progressInc *= 5;
            progressDuration *= 5;
          }
          if (progressDuration < 500) {
            progressInc *= 2;
            progressDuration *= 2;
          }
          if (progressDuration < 500) {
            progressInc *= 5;
            progressDuration *= 5;
          }
          digitalWrite(cPin, HIGH);
          announce.trigger();
          setNewState(doRunPump);
          break;
        case doRunPump:
          if (progressDuration && (now - timeProgress >= progressDuration)) {
            cPump->percentDone += progressInc;
            timeProgress = now;
            announce.trigger();
          }
          if (!(cPump->status & dpRunning) || aPump->executable() || (now - timeBase >= cPump->duration)) {
            digitalWrite(cPin, LOW);
            cPump->percentDone = 100;
            cPump->count++;
            cPump->clrStatusBit(dpRunning, dpRunningUpdated);
            announce.trigger();
            setNewState(doSelectPump);
          }
          break;
      }
    }
    if (announce.checkTimeout()) {
      writeTo('*', this, sizeof(Doses), true);
      Serial.print(F(" ad>  "));
      disp();
      incId();
      clrUpdated();
    }
  }

Note that Dose::executable silently removes any bogus run bits (when there is no duration),
which I probably should add to aTimer too, there I would have to check for onTime and offTime being zero.

bool executable() {
    if (status & dpRunning) {
      if (duration) {
        return true;
      }
      status &= ~(dpRunning + dpRunningUpdated);
    }
    return false;
  }

You should read/analyze/think more before writing code.

Again, non working reinvention of existing functionaly, messing with status bits, ignoring the hardware,

byte jumpToTimer(int newState)
  byte StopTimer()

instead of implementing the code that honors the bits that are there.

Whandall:
You define the behaviour.

"t3g" would set the run flag of timer 3.
The statemachine sees (after you changed it) that there are changes in a timer configuration,
t3 should start, so check if enabled and not 0,0, end the current cycle - if any is running -
and continue with t3.
Maybe additional states and a jumpTo variable are needed to handle that,
but a state machine does not care how many states it has.

You don't seem to understand what is going on, you should change that.

I'm getting really tired to repeat the same stuff over and over again,
without seeing you taking any notice of the text I write.