No ACK before Reset

Discussion about Z-Uno product. Visit http://z-uno.z-wave.me for more details.
dawiinci
Posts: 48
Joined: 14 Oct 2017 10:54

No ACK before Reset

Post by dawiinci » 24 Nov 2017 16:08

I get no ACK when I want to update. However, it works after pressing RST button.

Any ideas what this could be? Is the battery mode causing this?
Z-Wave Error device "test" does not support on command
Updated Code

Code: Select all


// V1.3

ZUNO_SETUP_SLEEPING_MODE(ZUNO_SLEEPING_MODE_SLEEPING);

ZUNO_SETUP_CHANNELS(
  ZUNO_SENSOR_MULTILEVEL(ZUNO_SENSOR_MULTILEVEL_TYPE_GENERAL_PURPOSE_VALUE, SENSOR_MULTILEVEL_SCALE_PERCENTAGE_VALUE, SENSOR_MULTILEVEL_SIZE_TWO_BYTES, SENSOR_MULTILEVEL_PRECISION_ZERO_DECIMALS, getterStatus),
  ZUNO_SWITCH_BINARY(getterNull, setterAutomower));

uint8_t requestStatusAutomower[5] = { 0x0F, 0x01, 0xF1, 0x00, 0x00 };
uint8_t autoAutomower[5] = { 0x0F, 0x81, 0x2C, 0x00, 0x01 };
uint8_t chargeAutomower[5] = { 0x0F, 0x81, 0x2C, 0x00, 0x03 };
uint8_t statusAutomower[5] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
uint8_t commandAutomower[5] = { 0x0F, 0x01, 0xF1, 0x00, 0x00 };
uint8_t leer[5] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

int statusInt;

void SerialWriteBuf(uint8_t *buffer, size_t size)
{
  while (size != 0) {
    Serial0.write((uint8_t) * buffer);
    buffer++;
    size--;
  }
}


void setup() {
  Serial0.begin(9600);

}

void loop() {


}

int getterStatus(void) {
  while (Serial0.available())
    Serial0.read();

  memcpy(commandAutomower, requestStatusAutomower, sizeof(commandAutomower));

  SerialWriteBuf(commandAutomower, sizeof(commandAutomower));
  Serial0.readBytes(statusAutomower, 5);

  statusInt = statusAutomower[4] << 8 | statusAutomower[3]; // Last two bytes inverted!
  return statusInt; // ID according to list (-1 is no RS-232)
}

int getterNull(void) {
  // no status, switch only triggers
  return 0;
}

void setterAutomower(byte value) {
  while (Serial0.available())
    Serial0.read();

  if (value == 1) {
    //switch on, Automower AUTO
    memcpy(commandAutomower, autoAutomower, sizeof(commandAutomower));

    SerialWriteBuf(commandAutomower, sizeof(commandAutomower)); //Serial0.write(commandAutomower, 5);
    Serial0.readBytes(statusAutomower, 5); //make sure interface has finished sending
  }

  else {
    //switch off, Automower HOME (charge)
    memcpy(commandAutomower, chargeAutomower, sizeof(commandAutomower));

    SerialWriteBuf(commandAutomower, sizeof(commandAutomower));
    Serial0.readBytes(statusAutomower, 5); //make sure interface has finished sending
  }
}

Last edited by dawiinci on 25 Nov 2017 18:46, edited 4 times in total.

User avatar
PoltoS
Posts: 4167
Joined: 26 Jan 2011 19:36

Re: No ACK before Reset

Post by PoltoS » 24 Nov 2017 16:33

I would suggest to minimize your getter and setter by moving all serial in loop. This should help and make this code even smaller.

dawiinci
Posts: 48
Joined: 14 Oct 2017 10:54

Re: No ACK before Reset

Post by dawiinci » 24 Nov 2017 17:25

I removed the content of loop and it works now. Probably caused by the delay. However I can't read from serial. Writing works.

What do you mean by putting serial to loop?

User avatar
PoltoS
Posts: 4167
Joined: 26 Jan 2011 19:36

Re: No ACK before Reset

Post by PoltoS » 24 Nov 2017 21:43

Putting all work with the Serial in the loop function leaving only simple variable assignment in the getter and setter

dawiinci
Posts: 48
Joined: 14 Oct 2017 10:54

Re: No ACK before Reset

Post by dawiinci » 25 Nov 2017 17:21

I'm a bit lost with serial on Arduino

Code: Select all

  while (Serial0.available())
    Serial0.read();
or

Code: Select all

    SerialWriteBuf(); 
    Serial0.readBytes();
Should the first code be in loop()? Can you explain what it actually does?

Thanks

petergebruers
Posts: 220
Joined: 26 Jul 2015 17:29

Re: No ACK before Reset

Post by petergebruers » 25 Nov 2017 17:58

I am not an expert but I would like to share this because it might help... I am sorry if it does not answer your question.

I'm use a CO2 sensor with serial interface, and this is how I "talk" to the sensor

In setup I do:

Code: Select all

  // Data exchange takes less than 10 ms. Add some safety margin...
  // This is less than the default, which is 1 s.
  Serial1.setTimeout(50L);
And in loop I do:

Code: Select all

uint8_t i = 0;
  for (i = 0; i < 9; i++) {
    Serial1.write(mhzCmdReadPPM[i]);
  }
  // Processing the command on the sensor takes less than 4 ms
  // Receiving the data takes about 10 ms
  uint8_t bytesRead = Serial1.readBytes((char *)response, 9);

  if (bytesRead != 9) {
    PG_DEBUG_PRN("Did not get 9 bytes from sensor. Blink 1 time.\n");
    blink(1);
    return;
  }
The for loop sends 9 bytes to the sensor ("sensor read ppm command" is in array mhzCmdReadPPM). Then I call readBytes with second parameter 9 because the sensor always sends 9 bytes back. blink(1) flashes the white LED if I get no response. This happens if the sensor is not connected or starting up... After this I check if the data has correct CRC and if the answer makes sense (is within 400 - 5000 ppm range).

I your code in post #1 looks remarkably similar... Except that your code does nothing with the number of bytes read, ie return code from readBytes is not used. So if communication is OK, I think your code will work. But if there is no answer, or it is not 5 bytes, that code might silently fail.

After the read bytes, your code does seem to test for an "empty" result (memcmp) but I am not sure if that has the same effect. I am not saying it is wrong either. But I think I'd first check if readBytes gave 5 bytes, then check if those bytes represent something (by calling memcpy). If the first test fails, I'd blink once. If the second test fails, blink twice.
SerialWriteBuf(commandAutomower, sizeof(commandAutomower));
Serial0.readBytes(statusAutomower, 5);

if (memcmp(statusAutomower, leer, 5) == 0)

But I am unsure why this is in your code:

Code: Select all

  while (Serial0.available())
    Serial0.read();
As far as I can tell, it will read data, but because the result is not stored, I think this simply flushes your input queue... Edit: so it is probably there to restore synchronisation in case something went wrong.

Did I understand your question correctly?
Last edited by petergebruers on 25 Nov 2017 18:26, edited 1 time in total.

dawiinci
Posts: 48
Joined: 14 Oct 2017 10:54

Re: No ACK before Reset

Post by dawiinci » 25 Nov 2017 18:25

Thanks for that detailed help.

I used this code before in the Arduino Yun, therefore I'm not even sure if it needs to be there. I had the impression that this is like an interrupt to catch read anything that comes in. But it makes sense to remove this if readBytes is enough. So maybe the Z-UNO is quicker or slower than the Yun.

Code: Select all

while (Serial0.available())
    Serial0.read();
You are probably right and I can remove the readBytes when I'm not checking anyway (maybe I should, but the interface is pretty stable). As far as I know serial connections do not check if I listen to, right? So the bytes are just "unheard" but it is not waiting. However, it might be helpful to make sure the interface is ready after sending.

Regarding the timing. Do I understand this correctly that it actually waits a second for an answer to be completely read? So maybe it is better in my case to add some seconds in case the response is slow. This timing seems to be only relevant when I want to gather data at a higher rate, right?

Thanks again

petergebruers
Posts: 220
Joined: 26 Jul 2015 17:29

Re: No ACK before Reset

Post by petergebruers » 25 Nov 2017 18:36

I was typing while you were typing :-)

So I just added this to the previous post: "I think this simply flushes your input queue... Edit: so it is probably there to restore synchronisation in case something went wrong."

From my tests with serial ports I remember this.But I cannot verify it because I am not at home. As soon as the chip detects a start bit, it starts reading a byte and buffers it for you. You then have to read it, to flush the queue (not immedately, the queue has a certain depth). Readbytes returns the number of bytes you ask for, if it gets that number within the timout period. The default is specified somewhere, I think it is 1s. I did not try to increase it, I only decreased it. I think it is a blocking call, so expect your code to be unreponsive if you increase it. If you do not know how long the response can take, I think you have to put readBytes in a loop and find a compromise on the time-out.

dawiinci
Posts: 48
Joined: 14 Oct 2017 10:54

Re: No ACK before Reset

Post by dawiinci » 25 Nov 2017 18:49

I made some optimization on the code in my first post. I hope it works now, but I have to test with hardware first. Might make sense to add a delay of 500 ms between sending and receiving.

What you are writing makes sense. So I better leave this code in my sketch.

petergebruers
Posts: 220
Joined: 26 Jul 2015 17:29

Re: No ACK before Reset

Post by petergebruers » 25 Nov 2017 18:57

Sounds like a plan... good luck!

Post Reply