attachInterrupt

Hi

I am writing my own 433 transmission library (inspired from rc-switch but some missing features added).

I am currently blocked by the attachInterrupt function to listen for packets. I'm getting the following error :

invalid use of non-static member function

After some Google I understood that I had to set this function static (and can't use
** **this->** **
then)

On the other hand, as we can see on line 550 here, the function is not static and there is an attachInterrupt.

RCSwitch.cpp

What am I missing ?

Thanks

How about posting your code ?

It's too ugly lol

h file

#include "Arduino.h"
#include <EEPROM.h>

#ifndef _radio_h
#define _radio_h

#define MAX_CHANGES 132
#define PULSE_DURATION 100

class Radio{

	public:
		Radio();
		void send(unsigned short destination, char * message, unsigned short source = 0, byte ttl = 255);
		void setPin(int pin);
		void setPairPin(int pin);
		void masterBroadcastPin(int pin);
		int isAvailable();
		void resetAvailable();
		char * getMessage();
		void enableReceive();
    void enableReceive(int pin);
    void setSerial(unsigned short serial);

    typedef struct HighLowPulses {
        int high;
        int low;
    };

	
	private:
		int pin;
		int repeat;
		int pairPin;
		unsigned short counter;
    unsigned short serial;
		int tolerance;
		int available = 0;
		char * message;

    unsigned long changes[MAX_CHANGES];
		
		HighLowPulses start = {4,2}; //4 high 2 low to start transmission
		HighLowPulses stop = {2,4}; //2 high 4 low to stop transmission
		HighLowPulses separator = {3,3}; //separates id, occurrence and code
		HighLowPulses one = {3,1}; //3 high 1 low to send binary 1
		HighLowPulses zero = {1,3}; //1 high 3 low to send binary 0
		
		unsigned short getCounter();
		static inline unsigned int diff(int A, int B);
		void incrementCounter();
		void resetCounter();
		void masterBroadcast();
		void registerMaster(unsigned short master);
		unsigned short getMaster();
		unsigned long getHash(unsigned short serial, unsigned short counter);
		bool validateHash(unsigned short serial, unsigned short counter, unsigned long hash);
		void transmit(HighLowPulses levels);
		void receive();
		int parseMessage(int changeCount);
};

#endif

cpp

#include "radio.h"

static inline unsigned int Radio::diff(int A, int B) {
    return abs(A - B);
}

Radio::Radio(){
    this->repeat = 2;
  	this->tolerance = 10;
  	this->message = calloc(1, sizeof(char));
}

void Radio::setPin(int pin){
    pinMode(pin, OUTPUT);
    this->pin = pin;
}

void Radio::setPairPin(int pin){
  	pinMode(pin, INPUT_PULLUP);
  	this->pairPin = pin;
}

//void masterBroadcastPin(int pin){
//	pinMode(pin, INPUT_PULLUP);
//	attachInterrupt(pin, masterBroadcast, FALLING)
//}

int Radio::isAvailable(){
    return this->available;
}

void Radio::resetAvailable(){
    this->available = 0;
    free(this->message);
    this->message = calloc(1, sizeof(char));
}

char * Radio::getMessage(){
    return this->message;
}

void Radio::enableReceive(int pin){
    pinMode(pin, INPUT);
    attachInterrupt(pin, receive, CHANGE);
}

void Radio::enableReceive(){
   this->enableReceive(this->pin);
}

unsigned short Radio::getCounter(){
	  return EEPROM.read(2) << 8 + EEPROM.read(3);
}

void Radio::incrementCounter(){
  	unsigned short counter = this->getCounter();
  	if(counter & 0b1111111111111111){
  		  this->resetCounter();
  	}
  	else {
    		counter++;
    		EEPROM.write(2, (byte) (counter & 0b1111111100000000) >> 8);
    		EEPROM.write(3, (byte) counter & 0b0000000011111111);
  	}
}

void Radio::resetCounter(){
  	EEPROM.write(2, 0);
  	EEPROM.write(3, 0);
}

void Radio::masterBroadcast(){
	  this->send(0, 0);
}

void Radio::registerMaster(unsigned short master){
  	EEPROM.write(0, (byte) (counter & 0b1111111100000000) >> 8);
  	EEPROM.write(1, (byte) counter & 0b0000000011111111);
}

unsigned short Radio::getMaster(){
	  return EEPROM.read(0) << 8 + EEPROM.read(1);
}

unsigned long Radio::getHash(unsigned short serial, unsigned short counter){
__________________________________________
}

bool Radio::validateHash(unsigned short serial, unsigned short counter, unsigned long hash){
  	unsigned long calculatedHash = this->getHash(serial, counter);
  	return calculatedHash == hash;
}

void Radio::setSerial(unsigned short serial){
    this->serial = serial;
}

void Radio::send(unsigned short destination, char * message, unsigned short source = 0, byte ttl = 255){
    int i = 0;
  	int bit;
  	unsigned short counter = this->getCounter();
  	unsigned long hash = this->getHash(this->serial, counter);
    if(source == 0){
        source = this->serial;
    }
	
    for(i; i < this->repeat; i++){
    		this->transmit(this->start);
    		
    		bit = sizeof(ttl) * 8 - 1;
    		while(bit >= 0){
      			if(ttl &  1 << bit){
      				  this->transmit(this->one);
      			}
      			else {
      				  this->transmit(this->zero);
      			}
      			bit--;
    		}
    		
    		this->transmit(this->separator);
    
    		bit = sizeof(source) * 8 - 1;
    		while(bit >= 0){
      			if(source &  1 << bit){
      				  this->transmit(this->one);
      			}
      			else {
      				  this->transmit(this->zero);
      			}
      			bit--;
    		}
    		
    		this->transmit(this->separator);
    
    		bit = sizeof(destination) * 8 - 1;
    		while(bit >= 0){
      			if(destination &  1 << bit){
      				  this->transmit(this->one);
      			}
      			else {
      				  this->transmit(this->zero);
      			}
      			bit--;
    		}
    		
    		this->transmit(this->separator);
    		
    		
    		bit = sizeof(counter) * 8 - 1;
    		while(bit >= 0){
      			if(counter &  1 << bit){
      				  this->transmit(this->one);
      			}
      			else {
      				  this->transmit(this->zero);
      			}
      			bit--;
    		}
    		
    		this->transmit(this->separator);
    		
            
    		bit = sizeof(hash) * 8 - 1;
    		while(bit >= 0){
      			if(hash &  1 << bit){
      				  this->transmit(this->one);
      			}
      			else {
      				  this->transmit(this->zero);
      			}
      			bit--;
    		}
    		
    		this->transmit(this->separator);
    
        int messageLen = strlen(message);
    		int i = 0;
        for(i; i < messageLen; i++){
            bit = sizeof(message) * 8 - 1;
            while(bit >= 0){
                if(message[i] &  1 << bit){
                    this->transmit(this->one);
                }
                else {
                    this->transmit(this->zero);
                }
              bit--;
            }
        }
    		
        this->transmit(this->stop);
    		
    		//Delay next transmission
        delayMicroseconds(PULSE_DURATION * 2);
    }
	this->incrementCounter();
}

void Radio::transmit(HighLowPulses levels){
  	pinMode(this->pin, OUTPUT);
  	digitalWrite(this->pin, HIGH);
  	delayMicroseconds(PULSE_DURATION * levels.high);
  	digitalWrite(this->pin, LOW);
  	delayMicroseconds(PULSE_DURATION * levels.low);
}

int Radio::parseMessage(int changeCount){
    if(diff(this->changes[1], this->start.high * PULSE_DURATION) < this->tolerance && diff(this->changes[2], this->start.low * PULSE_DURATION) < this->tolerance){
    		Serial.println("Sync received");
    		Serial.println(changeCount);
    		int i =0;
    		for(i; i < changeCount; i++){
      			Serial.print(i);
      			Serial.print(":");
      			Serial.println(this->changes[i]);
    		}
        return 1;
    }
    return 0;
}

void Radio::receive(){
    static unsigned long lastTime = 0;
    static int changeCount = 0;

    unsigned long time = micros();
    int duration = time - lastTime;

    if(changeCount > MAX_CHANGES){
        changeCount = 0;
		    time = 0;
    }
	
    this->changes[changeCount] = duration;
    changeCount++;
    lastTime = time;
	  parseMessage(changeCount);
}

Anyone spotted something ?

Thanks

I edited the code above, corrected multiple errors and censored something.

The argument to attachInterrupt needs to be a static function and can’t use “this”, because when the function is actually called from the interrupt context, this is no “this”?

Note: attachInterrupt() takes and Interrupt Number, not a Pin Number. Use the function digitalPinToInterrupt(pin) to do the translation:

    attachInterrupt(digitalPinToInterrupt(pin), ISRfunction, RISING);

Make sure that the pin you have chosen supports an external interrupt:

westfw:
The argument to attachInterrupt needs to be a static function and can’t use “this”, because when the function is actually called from the interrupt context, this is no “this”?

Thanks to your hint I could almost finish my library today. I still need to clean up stuff

johnwasser:
Note: attachInterrupt() takes and Interrupt Number, not a Pin Number. Use the function digitalPinToInterrupt(pin) to do the translation:

    attachInterrupt(digitalPinToInterrupt(pin), ISRfunction, RISING);

Make sure that the pin you have chosen supports an external interrupt:
attachInterrupt() - Arduino Reference

Yes I spotted that and corrected it in the meantime.

Thanks

If you want to support multiple simultaneous radios you will need a static ISR for each one. You can have an array of them and dole them out as radios get added. Here is how that might look. The ISR's are at the bottom. (I merged the .h and .cpp into a single .ino for testing).

NOTE: I have compiler warnings set to ALL and there are a number of warnings that look like they indicate coding mistakes (like "A << 8 + B" which I think is parsing as "A << (8 + B)").

#include <EEPROM.h>


#define MAX_CHANGES 132
#define PULSE_DURATION 100






class Radio
{


  public:
    Radio();
    void send(unsigned short destination, char * message, unsigned short source = 0, byte ttl = 255);
    void setPin(int pin);
    void setPairPin(int pin);
    void masterBroadcastPin(int pin);
    int isAvailable();
    void resetAvailable();
    char * getMessage();
    void enableReceive();
    void enableReceive(int pin);
    void setSerial(unsigned short serial);


    typedef struct HighLowPulses
    {
      int high;
      int low;
    };


    static void receiveISR0();
    static void receiveISR1();
    static void receiveISR2();
    static void receiveISR3();




  private:
    static Radio *radios[4];
    static void(*ISRList[4])();
    static byte radioCount;
    byte radioIndex;  // Index into ISR tables


    int pin;
    int repeat;
    int pairPin;
    unsigned short counter;
    unsigned short serial;
    int tolerance;
    int available = 0;
    char * message;


    unsigned long changes[MAX_CHANGES];


    HighLowPulses start = {4, 2}; //4 high 2 low to start transmission
    HighLowPulses stop = {2, 4}; //2 high 4 low to stop transmission
    HighLowPulses separator = {3, 3}; //separates id, occurrence and code
    HighLowPulses one = {3, 1}; //3 high 1 low to send binary 1
    HighLowPulses zero = {1, 3}; //1 high 3 low to send binary 0


    unsigned short getCounter();
    static inline unsigned int diff(int A, int B);
    void incrementCounter();
    void resetCounter();
    void masterBroadcast();
    void registerMaster(unsigned short master);
    unsigned short getMaster();
    unsigned long getHash(unsigned short serial, unsigned short counter);
    bool validateHash(unsigned short serial, unsigned short counter, unsigned long hash);
    void transmit(HighLowPulses levels);
    void receive();
    int parseMessage(int changeCount);
};




byte Radio::radioCount = 0;
void(*ISRList[])() = {Radio::receiveISR0, Radio::receiveISR1, Radio::receiveISR2, Radio::receiveISR3};


static inline unsigned int Radio::diff(int A, int B)
{
  return abs(A - B);
}


Radio::Radio()
{
  repeat = 2;
  tolerance = 10;
  message = calloc(1, sizeof(char));
  radioIndex = radioCount++;
  radios[radioIndex] = this;
}


void Radio::setPin(int pin)
{
  pinMode(pin, OUTPUT);
  pin = pin;
}


void Radio::setPairPin(int pin)
{
  pinMode(pin, INPUT_PULLUP);
  pairPin = pin;
}


//void masterBroadcastPin(int pin){
//  pinMode(pin, INPUT_PULLUP);
//  attachInterrupt(pin, masterBroadcast, FALLING)
//}


int Radio::isAvailable()
{
  return available;
}


void Radio::resetAvailable()
{
  available = 0;
  free(message);
  message = calloc(1, sizeof(char));
}


char * Radio::getMessage()
{
  return message;
}


void Radio::enableReceive(int pin)
{
  pinMode(pin, INPUT);
  attachInterrupt(pin, ISRList[radioIndex], CHANGE);
}


void Radio::enableReceive()
{
  enableReceive(pin);
}


unsigned short Radio::getCounter()
{
  return EEPROM.read(2) << 8 + EEPROM.read(3);
}


void Radio::incrementCounter()
{
  unsigned short counter = getCounter();
  if (counter & 0b1111111111111111)
  {
    resetCounter();
  }
  else
  {
    counter++;
    EEPROM.write(2, (byte) (counter & 0b1111111100000000) >> 8);
    EEPROM.write(3, (byte) counter & 0b0000000011111111);
  }
}


void Radio::resetCounter()
{
  EEPROM.write(2, 0);
  EEPROM.write(3, 0);
}


void Radio::masterBroadcast()
{
  send(0, 0);
}


void Radio::registerMaster(unsigned short master)
{
  EEPROM.write(0, (byte) (counter & 0b1111111100000000) >> 8);
  EEPROM.write(1, (byte) counter & 0b0000000011111111);
}


unsigned short Radio::getMaster()
{
  return EEPROM.read(0) << 8 + EEPROM.read(1);
}


unsigned long Radio::getHash(unsigned short serial, unsigned short counter)
{
  //__________________________________________
}


bool Radio::validateHash(unsigned short serial, unsigned short counter, unsigned long hash)
{
  unsigned long calculatedHash = getHash(serial, counter);
  return calculatedHash == hash;
}


void Radio::setSerial(unsigned short serial)
{
  serial = serial;
}


void Radio::send(unsigned short destination, char * message, unsigned short source = 0, byte ttl = 255)
{
  int i = 0;
  int bit;
  unsigned short counter = getCounter();
  unsigned long hash = getHash(serial, counter);
  if (source == 0)
  {
    source = serial;
  }


  for (i; i < repeat; i++)
  {
    transmit(start);


    bit = sizeof(ttl) * 8 - 1;
    while (bit >= 0)
    {
      if (ttl &  1 << bit)
      {
        transmit(one);
      }
      else
      {
        transmit(zero);
      }
      bit--;
    }


    transmit(separator);


    bit = sizeof(source) * 8 - 1;
    while (bit >= 0)
    {
      if (source &  1 << bit)
      {
        transmit(one);
      }
      else
      {
        transmit(zero);
      }
      bit--;
    }


    transmit(separator);


    bit = sizeof(destination) * 8 - 1;
    while (bit >= 0)
    {
      if (destination &  1 << bit)
      {
        transmit(one);
      }
      else
      {
        transmit(zero);
      }
      bit--;
    }


    transmit(separator);




    bit = sizeof(counter) * 8 - 1;
    while (bit >= 0)
    {
      if (counter &  1 << bit)
      {
        transmit(one);
      }
      else
      {
        transmit(zero);
      }
      bit--;
    }


    transmit(separator);




    bit = sizeof(hash) * 8 - 1;
    while (bit >= 0)
    {
      if (hash &  1 << bit)
      {
        transmit(one);
      }
      else
      {
        transmit(zero);
      }
      bit--;
    }


    transmit(separator);


    int messageLen = strlen(message);
    int i = 0;
    for (i; i < messageLen; i++)
    {
      bit = sizeof(message) * 8 - 1;
      while (bit >= 0)
      {
        if (message[i] &  1 << bit)
        {
          transmit(one);
        }
        else
        {
          transmit(zero);
        }
        bit--;
      }
    }


    transmit(stop);


    //Delay next transmission
    delayMicroseconds(PULSE_DURATION * 2);
  }
  incrementCounter();
}


void Radio::transmit(HighLowPulses levels)
{
  pinMode(pin, OUTPUT);
  digitalWrite(pin, HIGH);
  delayMicroseconds(PULSE_DURATION * levels.high);
  digitalWrite(pin, LOW);
  delayMicroseconds(PULSE_DURATION * levels.low);
}


int Radio::parseMessage(int changeCount)
{
  if (diff(changes[1], start.high * PULSE_DURATION) < tolerance && diff(changes[2], start.low * PULSE_DURATION) < tolerance)
  {
    Serial.println("Sync received");
    Serial.println(changeCount);
    int i = 0;
    for (i; i < changeCount; i++)
    {
      Serial.print(i);
      Serial.print(":");
      Serial.println(changes[i]);
    }
    return 1;
  }
  return 0;
}


void Radio::receive()
{
  static unsigned long lastTime = 0;
  static int changeCount = 0;


  unsigned long time = micros();
  int duration = time - lastTime;


  if (changeCount > MAX_CHANGES)
  {
    changeCount = 0;
    time = 0;
  }


  changes[changeCount] = duration;
  changeCount++;
  lastTime = time;
  parseMessage(changeCount);
}






void Radio::receiveISR0()
{
  radios[0]->receive();
}


void Radio::receiveISR1()
{
  radios[1]->receive();
}


void Radio::receiveISR2()
{
  radios[2]->receive();
}


void Radio::receiveISR3()
{
  radios[3]->receive();
}