Hardware interrupt and zunoSendReport()

Discussion about Z-Uno product. Visit http://z-uno.z-wave.me for more details.
Post Reply
splitfile
Posts: 9
Joined: 11 Jul 2019 14:04

Hardware interrupt and zunoSendReport()

Post by splitfile »

Hi,

I'm experiencing some intermittent problem with my Zuno. Sometimes Zuno stops reporting my sensor values.
I'm powering the Zuno via USB (output 1A).

I have started to wonder if the problem has something to do with interrupts...

I have an IR-sensor that counts the LED-blinks on my power-meter. This is to calculate the watt and kwh my house is using.
Every time the power-meter LED blinks the interrupt callback function is called:

Code: Select all

ZUNO_SETUP_ISR_INT0(onPulse);

Code: Select all

void setup()
{
  // Enable interrupt. Triggered when light pulse is detected
  zunoExtIntMode(ZUNO_EXT_INT0, RISING);
}

Can the interrupt cause any trouble for my main -loop?

Code: Select all

void loop()
{
  zunoSendReport(ZUNO_CHANNEL_NUMBER_ONE); // send report over the Z-Wave to the controller
  zunoSendReport(ZUNO_CHANNEL_NUMBER_TWO); // send report over the Z-Wave to the controller

  delay(60000); //sleep 60s
}
I mean can there be problems if the interrupt is called while zunoSendReport() is executing?

Thanks!
/S
p0lyg0n1
Posts: 242
Joined: 04 Aug 2016 07:14

Re: Hardware interrupt and zunoSendReport()

Post by p0lyg0n1 »

Hi,
Could you provide some extra details? The most important thing is what do you do inside the interrupt handler. If you provide the full code of the sketch will be great.

Best regards,
Alex.
rkv
Posts: 4
Joined: 15 Jul 2019 13:13

Re: Hardware interrupt and zunoSendReport()

Post by rkv »

We did simple code that works fine with razberry. Give us full code of your program.

Code: Select all

ZUNO_SETUP_CHANNELS(
  ZUNO_METER(ZUNO_METER_TYPE_ELECTRIC, ZUNO_METER_RESETABLE, ZUNO_METER_ELECTRIC_SCALE_PULSECOUNT, METER_SIZE_TWO_BYTES, METER_PRECISION_ZERO_DECIMALS, second_channel_getter, resetter),
  ZUNO_SENSOR_MULTILEVEL(ZUNO_SENSOR_MULTILEVEL_TYPE_VOLTAGE, SENSOR_MULTILEVEL_SCALE_VOLT, SENSOR_MULTILEVEL_SIZE_TWO_BYTES, SENSOR_MULTILEVEL_PRECISION_TWO_DECIMALS, first_channel_getter)
);

ZUNO_SETUP_ISR_INT0(onPulse);

word current_voltage;
word current_pulses = 0;

void setup(){
  zunoExtIntMode(ZUNO_EXT_INT0, RISING);  
  Serial.begin();
}

void loop(){
  current_voltage = 0;
  zunoSendReport(1); // send report over the Z-Wave to the controller
  zunoSendReport(2); // send report over the Z-Wave to the controller
  delay(600); 
}

void onPulse(){
  current_voltage = 309;
  current_pulses++;
  Serial.println(current_voltage);
  Serial.println(current_pulses);
}

word first_channel_getter(){
  return current_voltage;
}

word second_channel_getter(){
  return current_pulses;
}
void resetter(){
  current_pulses = 0;
}
splitfile
Posts: 9
Joined: 11 Jul 2019 14:04

Re: Hardware interrupt and zunoSendReport()

Post by splitfile »

Hi and thanks for your reply.

Would it be sufficient if I power the zuno via USB and use a 0.550 mA power supply? Keep in mind that it is the Zuno and one of these that I'm powering:
Image

I'm also experimenting with the range between the controller and the Zuno. Right now I'm testing with 2 meters (same room).

This is the full sketch.

Code: Select all

/*
 * Calculates Watt and KWh
 */

#define DEBUG       0 // 1=On, 0=Off
 
// channel number
#define ZUNO_CHANNEL_NUMBER_ONE   1
#define ZUNO_CHANNEL_NUMBER_TWO   2

// Number of blinks per kWh of your meter
#define PULSE_FACTOR 1000

// Pulses per watt hour
float ppwh = ((float)PULSE_FACTOR)/1000;

// Counting the light pulse
volatile uint32_t pulseCount = 0;

volatile uint32_t lastBlink = 0;

volatile uint32_t newBlink = 0;
volatile uint32_t interval = 0;

// The value to report back to controller
volatile uint32_t watt = 0;

// Setup the Z-Wave channels
// you can read more on http://z-uno.z-wave.me/Reference/

ZUNO_SETUP_CHANNELS(
  //Channel 1
  ZUNO_SENSOR_MULTILEVEL(ZUNO_SENSOR_MULTILEVEL_TYPE_POWER, 
                         SENSOR_MULTILEVEL_SCALE_WATT, 
                         SENSOR_MULTILEVEL_SIZE_TWO_BYTES, 
                         SENSOR_MULTILEVEL_PRECISION_ZERO_DECIMALS, 
                         get_watt),
  //Channel 2
  ZUNO_METER(ZUNO_METER_TYPE_ELECTRIC, 
             METER_RESET_ENABLE,
             ZUNO_METER_ELECTRIC_SCALE_KWH,
             METER_SIZE_FOUR_BYTES,
             METER_PRECISION_TWO_DECIMALS,
             get_kwh,
             reset_kwh)
);


// Set the interrupt callback function
ZUNO_SETUP_ISR_INT0(onPulse);



void setup() 
{
#ifdef DEBUG
  Serial.begin();
  Serial.println("Inside setup");
#endif

  // Enable interrupt. Triggered when light pulse is detected
  zunoExtIntMode(ZUNO_EXT_INT0, RISING);
}

void loop()
{
#ifdef DEBUG
  Serial.println("Sending on channel 1");
#endif
  zunoSendReport(ZUNO_CHANNEL_NUMBER_ONE); // send report over the Z-Wave to the controller

#ifdef DEBUG
  Serial.println("Sending on channel 2");
#endif
  zunoSendReport(ZUNO_CHANNEL_NUMBER_TWO); // send report over the Z-Wave to the controller

  delay(60000); //sleep 60s
}

//
// Called when a IR light pulse is detected
//
void onPulse()
{
  #ifdef DEBUG
    Serial.println("onPulse! - Light pulse detected");
  #endif

  newBlink = millis();
  interval = newBlink - lastBlink;
  
  watt = (3600000.0 / interval) / ppwh;
  lastBlink = newBlink;

  pulseCount++;
}

uint32_t get_watt()
{
  uint32_t wattNow = watt;
  watt = 0;

  return wattNow;
}

void reset_watt()
{
}

uint32_t get_kwh()
{
  // float = 4 bytes
  float kWh = ((float)pulseCount/((float)PULSE_FACTOR));

  return (100 * kWh); // For test purpose. Investigate why we need  *100. Might be decimal thing...
}

void reset_kwh()
{
  Serial.println("reset_kwh() called");
  //pulseCount = 0;
}
It is usually working many hours, but eventually the sensor reports stops coming in to the controller.

/S
splitfile
Posts: 9
Joined: 11 Jul 2019 14:04

Re: Hardware interrupt and zunoSendReport()

Post by splitfile »

Hi again!

After some more testing, it feels like it might be a software/interrupt issue. I tried the following.
I put some adhesive tape over the IR sensor so that the hardware interrupt wouldn't trigger. Then I put all of it back in place, covering my power meter. Powering the Z-uno via USB (Output: 0.550 mA).
With this setup the Zuno reports back values (always zero because of the adhesive tape) every minute like it should. So this way it works. No hanging/missing sensor reports.

What do you think. Can it be a problem with "millis()"? I call that function in the interrupt function. Or could be some issue that the HW interrupt and zunoSendReport() is having problems?

I was thinking of moving zunoSendReport() in to the interrupt function. Is that a bad idea?

All ideas welcome :-)
tetrixx
Posts: 1
Joined: 02 Aug 2019 00:02

Re: Hardware interrupt and zunoSendReport()

Post by tetrixx »

I read that you should be careful with Serial in interrupt handlers: https://www.arduino.cc/reference/en/lan ... interrupt/
That page says that millis() does not increment inside the handler but it might work for what you are doing.
splitfile
Posts: 9
Joined: 11 Jul 2019 14:04

Re: Hardware interrupt and zunoSendReport()

Post by splitfile »

Hi and thank you. I'm not using "Serial" (only use it while debugging).

However I have (after a lot of testing) come to the conclusion that the problem must be related to HW interrupts and zunoSendReport().

After I moved zunoSendReport() from the main loop to the HW interrupt function it is now working.

Code: Select all

void loop()
{
  delay(10000); //sleep 10s
}

Code: Select all

void onPulse()
{
  now = newBlink = millis();
  interval = newBlink - lastBlink;
  watt = (3600000.0 / interval) / ppwh;
  lastBlink = newBlink;

  pulseCount++;

  if ((now - lastSend) > SEND_FREQUENCY)
  {
    zunoSendReport(ZUNO_CHANNEL_NUMBER_ONE); // send report over the Z-Wave to the controller
    zunoSendReport(ZUNO_CHANNEL_NUMBER_TWO); // send report over the Z-Wave to the controller
    lastSend = now;
  }
}

If the devs want me to test some updates in the zuno-code I can help debug.

/S
Post Reply