Go Down

Topic: Disable I2C interrupts in wire.h (Read 1 time) previous topic - next topic

ScottG

I have a sketch where my Arduino acts as an I2C slave.  I'm using the wire.h library and I want to know if Wire.h I2C communication uses interrupts.  Another part of my sketch receives wireless data via a cc1101 chip (I'm using a panStamp).  The cc1101 part of the code uses an interrupt and I'm concerned that if I2C uses an interrupt, it may cause problems if I don't disable it.  So, does I2C use interrupt?  If so, how do I disable then re-enable it.  Here's my sketch for reference

Code: [Select]

#include "EEPROM.h"   
#include "cc1101.h"   // http://code.google.com/p/panstamp/source/browse/trunk/arduino/libraries/panstamp/cc1101.h
#include <Wire.h>     // for I2C communication with main arduino

// The networkAdress of panStamp sender and receiver must be the same
byte panStampNetworkAdress =   91;  // Network address for all pool panStamps
byte receiverAddress =         99;  // Device address of this panStamp
const byte addrSlaveI2C =      21;  // I2C Slave address of this device
const byte addrLevelSensor =    1;  // panStamp device address for low water sensor
const byte panStampOffline =  255;  // Send this to I2C master in the panStamp Rx address to indicate panStamp is offline
const byte panStampOK      =    0;  // panStamp is successfully transmitting data
const uint32_t panStampTimeout = 600000; // 10 minute timeout for panStamps.  If no connections in 10 minutes, tell master that panStamp is offline

#define I2C_PACKET_LEN 5 // bytes in I2C Packet
byte I2C_Packet[I2C_PACKET_LEN];   // Array to hold data sent over I2C to main Arduino
uint32_t lastRxSuccess;   // miliseconds since last successful receipt of panStamp data.

CCPACKET packet;  // panStamp data http://code.google.com/p/panstamp/source/browse/trunk/arduino/libraries/panstamp/ccpacket.h

// The connection to the hardware chip CC1101 the RF Chip
CC1101 cc1101;  // http://code.google.com/p/panstamp/wiki/CC1101class

// flag indicates wireless packet has been received
boolean packetAvailable = false;       


// Handle interrupt from CC1101 (INT 0)
void cc1101signalsInterrupt(void)
{
  // set the flag that a package is available
  packetAvailable = true;
} // cc1101signalsInterrupt()


void setup()
{
  delay(3000);
  Serial.begin(9600);
  Serial.println(F("Begin panStamp Rx setup()"));

  Wire.begin(addrSlaveI2C);    // Initiate the Wire library and join the I2C bus
  Wire.onRequest(wireRequestEvent); // Register a function to be called when a master requests data from this slave device.
  Serial.println(F("Wire library initialized"));

  cc1101.init(); // initialize the RF Chip in panStamp
  cc1101.setSyncWord(&panStampNetworkAdress, false);  // Set network address (pointer), false parameter tells function not to save to EEPROM
  // This receiverAddress needs to match the receiverAddress in the Tx panStamp
  cc1101.setDevAddress(receiverAddress, false);  // false parameter tells function not to save to EEPROM
  cc1101.setRxState(); // Set this panStamp to be a receiver
 
  // Enable wireless reception interrupt
  attachInterrupt(0, cc1101signalsInterrupt, FALLING);
   
}  // end setup()


void loop()
{
 
  // Get data from water level sensor panStamp
  if(packetAvailable)
  {
    // clear the flag
    packetAvailable = false;
   
    // Disable wireless reception interrupt so this code finishes executing without inturruption
    detachInterrupt(0);
   
    if(cc1101.receiveData(&packet) > 0)
    {
      if (packet.crc_ok && packet.length > 1)
      {
        lastRxSuccess = millis(); // Track time of successful receipt of panStamp data from transmitter
       
        // print received data
        Serial.print(packet.data[3]); // Low level
        Serial.print("\t");
        int Vcc = 0;
        Vcc  = packet.data[4] << 8; 
        Vcc |= packet.data[5];
        Serial.print(Vcc); 
        Serial.print("\t");
        Serial.print(millis()/1000);
        Serial.println();
     
        I2C_Packet[0] = addrSlaveI2C;
        // If sketch hasn't received any data from the panStamp in a while then
        // set the panStamp Tx byte to indicate it's offline by setting it to 255
        if ((long)( millis() - lastRxSuccess) > panStampTimeout )   
        { I2C_Packet[1] = panStampOffline; }
        else
        { I2C_Packet[1] = panStampOK; }
        // Copy data from panStamp packet to I2C packet array
        I2C_Packet[2] = packet.data[3];   // Low water level
        I2C_Packet[3] = packet.data[4];   // Battery voltage
        I2C_Packet[4] = packet.data[5];   // Battery voltage

      } // packet is okay
    }  // got packet
   
    // Enable panStamp wireless reception interrupt
    attachInterrupt(0, cc1101signalsInterrupt, FALLING);
  }
 
} // end loop()


// function that executes whenever data is requested by master
void wireRequestEvent()
{
  // Send data to I2C master
  Wire.write(I2C_Packet, I2C_PACKET_LEN);
 
} // end wireRequestEvent()



Coding Badly

Quote
The cc1101 part of the code uses an interrupt and I'm concerned that if I2C uses an interrupt, it may cause problems if I don't disable it.  So, does I2C use interrupt?


Why would that cause a problem?  You are using Serial which is interrupt driven.  Why are you concerned about I2C interrupts but not Serial interrupts?

ScottG

I don't know anything about how serial works.  So your saying when I do a Serial.print() it uses interrupts?

My concern is if my sketch is in the  if(cc1101.receiveData(&packet) > 0) section and then an I2C request comes in, the sketch will jump to wireRequestEvent() and potentially mess up reading cc1101 data.  Maybe that's not a problem.  I'm trying to figure out if I have a potential problem or not.

Nick Gammon

Code: [Select]
// flag indicates wireless packet has been received
boolean packetAvailable = false;        


// Handle interrupt from CC1101 (INT 0)
void cc1101signalsInterrupt(void)
{
 // set the flag that a package is available
 packetAvailable = true;
} // cc1101signalsInterrupt()


Variables set by an ISR should be declared volatile.

http://gammon.com.au/interrupts

Quote
So, does I2C use interrupt?  


Yes it does.

Quote
If so, how do I disable then re-enable it.


Why do you want to?

Read the link above, get back to us if you have more questions. Also:


http://gammon.com.au/i2c
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

ScottG

Thanks Nick, that's a very good article on interrupts.  Using volatile variables with interrupts was something I didn't know (and lots of other stuff!).  Seems like I'm okay with the I2C they way it is and I don't need to disable anything while the cc1101 is receiving data.

Go Up