Jump to content
p2baron

[SOLVED] Using CapTouch lib from a class

Recommended Posts

Hi,


 


I am working on a wireless touch controller for 433Mhz dimmer modules.


The idea is simple. When a touch button is touched a 433Mhz command is send to a wireless dimmer module. 


A single or double tap switches the module on or off, holding it will cycle it from dim-bright-dim until the button is released.


 


For this I am using the CapTouch library posted in library section of this forum.


 


I have create a class for this to enable me to quickly add more sensors. 


However when I initialise more than one class the code doesn't work anymore. And I can't figure out why.


The code still compiles but a touch is registered constantly. (all lights are on)


 


Can anyone look in my code and give me some pointers?



#include <RemoteTransmitter.h>
#include <CapTouch.h>

//KaKuTransmitter kaKuTransmitter(11);

#ifndef touchDimmer_h
#define touchDimmer_h
class touchDimmer {
public:
touchDimmer(char housecode, byte unit_number, byte pin);
void begin();
void check();
private:
long _lTimeHigh;
long _lHighTimer;
long _lLowTimer;
long _lTimeLow;
long _lTimer;
int _iPulse;
int _iNumReadings;
int _iReadings[10]; // the readings from the analog input
int _iIndex; // the index of the current reading
int _iTotal; // the running total
float _average; // the average
boolean _bCurState;
boolean _bPrevState;
boolean _bDimmerMode;
boolean _bButtonState;
int _iHighPulse; // Time in millis that is nessesary to count as high
int _iLowPulse; // Time in millis that is nessesary to count as low
byte _housecode;
byte _unit_number;
byte _pin;
// protected:
CapTouch* button;
};
#endif

touchDimmer::touchDimmer(char housecode, byte unit_number, byte pin)
{
_housecode = housecode;
_unit_number = unit_number;
_pin = pin;
button = new CapTouch(_pin,TOUCH_BUTTON);
}

void touchDimmer::begin()
{
_lTimeHigh = 0;
_lHighTimer = 0;
_lLowTimer = 0;
_lTimeLow = 0;
_lTimer = 0;
_iPulse = 0;
_iNumReadings = 10;
_iReadings[_iNumReadings];
_iIndex = 0;
_iTotal = 0;
_average = 0;
_bCurState = false;
_bPrevState = false;
_bDimmerMode = false;
_bButtonState = false;
_iHighPulse = 20;
_iLowPulse = 20;
for (int thisReading = 0; thisReading < _iNumReadings; thisReading++) {
_iReadings[thisReading] = 0;
}
};

void touchDimmer::check()
{
_lTimer = millis();
_iTotal= _iTotal - _iReadings[_iIndex];
_iReadings[_iIndex] = button->isTouched();
_iTotal= _iTotal + _iReadings[_iIndex];
_iIndex = _iIndex + 1;
if (_iIndex >= _iNumReadings)
_iIndex = 0;
_average = _iTotal / _iNumReadings;
if(_iTotal == _iNumReadings) {
_bCurState = HIGH;
if(_bCurState != _bPrevState) {
_lTimeHigh = _lTimer;
digitalWrite(RED_LED,HIGH);
if((_lHighTimer % _iHighPulse) == 0) {
if(_bCurState != _bPrevState) {
_iPulse++;
_bPrevState = _bCurState;
digitalWrite(RED_LED,HIGH);
}
}
}
_lHighTimer = _lTimer - _lTimeHigh;
if((_lHighTimer > 100)) {
if(_bDimmerMode == LOW) {
Serial.println("Dimmer ON");
_bDimmerMode = HIGH;
_iPulse = 0;
digitalWrite(GREEN_LED, HIGH);
// kaKuTransmitter.sendSignal(_housecode, _unit_number, true);
}
}
}

if(_iTotal == 0) {
_bCurState = LOW;
_lTimeLow = _lTimer;
_lLowTimer = _lTimer - _lTimeLow;
if (_bDimmerMode == HIGH) {
_bDimmerMode = LOW;
digitalWrite(GREEN_LED, LOW);
// kaKuTransmitter.sendSignal(_housecode, _unit_number, true);
}
if (((_lTimer - _lTimeHigh) > 300) && (_iPulse > 0)){
switch(_iPulse){
case 1:
// kaKuTransmitter.sendSignal(_housecode, _unit_number, true);
break;
case 2:
// kaKuTransmitter.sendSignal(_housecode, _unit_number, false);
break;
}
_iPulse = 0;
}
if((_lLowTimer % _iLowPulse) == 0) {
if(_bCurState != _bPrevState) {
_bPrevState = _bCurState;
digitalWrite(RED_LED,LOW); // Light the led
}
}
}
}
touchDimmer test = touchDimmer('N',15,10);
touchDimmer test2 = touchDimmer('N',15,5);
void setup() {
pinMode(RED_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
digitalWrite(GREEN_LED, LOW);
digitalWrite(RED_LED, LOW);
test.begin();
test2.begin();
}
void loop() {
test.check();
test2.check();
}

Share this post


Link to post
Share on other sites

Are you sure you don't run out of memory, a quick summing tells me that your touchDimmer objects are about 70 bytes large.

 

I'd suggest you avoid using new/delete on an embedded platform, because it will force your compiler to do memory management (most/all MSP430s do not have an MMU). You could either do a static initialisation of the button member, or even derive touchDimmer from CapTouch Static initialisation should work as follows:

touchDimmer::touchDimmer(char housecode, byte unit_number, byte pin) 
: _housecode(housecode)
, _unit_number(unit_number)
, _pin(pin)
, button(CapTouch(_pin,TOUCH_BUTTON))
{
}

Also remove the pointer attribute from the button member, as it is now a by-value member. This would avoid linking memory management routines, which saves a lot of space.

Share this post


Link to post
Share on other sites

Thanks that did it!

 

Still having some memory problem though.

It gets stuck when I use it a couple of times. But it is working on multiple pins!!

 

I will do some trimming.  :smile:

 

Anyway here is the new code:

#include <RemoteTransmitter.h>
#include <CapTouch.h>

//KaKuTransmitter kaKuTransmitter(11);

#ifndef touchDimmer_h
#define touchDimmer_h
class touchDimmer {
public:
  touchDimmer(char housecode, byte unit_number, byte pin);
  void begin();
  void check();
private:
  long _lTimeHigh;
  long _lHighTimer;
  long _lLowTimer;
  long _lTimeLow;
  long _lTimer;
  int _iPulse;
  int _iNumReadings;
  int _iReadings[10];      // the readings from the analog input
  int _iIndex;                  // the index of the current reading
  int _iTotal;                  // the running total
  float _average;              // the average 
  boolean _bCurState;
  boolean _bPrevState;
  boolean _bDimmerMode;
  boolean _bButtonState;
  int _iHighPulse;		// Time in millis that is nessesary to count as high
  int _iLowPulse;		// Time in millis that is nessesary to count as low
  byte _housecode;
  byte _unit_number;
  byte _pin;
  //    protected:
  CapTouch button;
};
#endif

//touchDimmer::touchDimmer(char housecode, byte unit_number, byte pin) 
//{
//  _housecode = housecode;
//  _unit_number = unit_number;
//  _pin = pin;
//  button = new CapTouch(_pin,TOUCH_BUTTON);
//}

touchDimmer::touchDimmer(char housecode, byte unit_number, byte pin) 
: 
  _housecode(housecode)
  ,_unit_number(unit_number)
  , _pin(pin)
  ,button(CapTouch(_pin,TOUCH_BUTTON))
{
}

void touchDimmer::begin()
{
  _lTimeHigh = 0;
  _lHighTimer = 0;
  _lLowTimer = 0;
  _lTimeLow = 0;
  _lTimer = 0;
  _iPulse = 0;
  _iNumReadings = 10;
  _iReadings[_iNumReadings];
  _iIndex = 0;      
  _iTotal = 0;         
  _average = 0;         
  _bCurState = false;
  _bPrevState = false;
  _bDimmerMode = false;
  _bButtonState = false;
  _iHighPulse = 20;
  _iLowPulse = 20;
  for (int thisReading = 0; thisReading < _iNumReadings; thisReading++) {
    _iReadings[thisReading] = 0;
  }
};

void touchDimmer::check()
{
  _lTimer = millis();
  _iTotal= _iTotal - _iReadings[_iIndex];  
  _iReadings[_iIndex] = button.isTouched();
  _iTotal= _iTotal + _iReadings[_iIndex]; 
  _iIndex = _iIndex + 1;
  if (_iIndex >= _iNumReadings)              
    _iIndex = 0;                           
  _average = _iTotal / _iNumReadings;  
  if(_iTotal == _iNumReadings) {
    _bCurState = HIGH;
    if(_bCurState != _bPrevState) {
      _lTimeHigh = _lTimer;
      digitalWrite(RED_LED,HIGH);
      if((_lHighTimer % _iHighPulse) == 0) {
        if(_bCurState != _bPrevState) {
          _iPulse++;
          _bPrevState = _bCurState;
          digitalWrite(RED_LED,HIGH);
        }     
      }     
    }
    _lHighTimer = _lTimer - _lTimeHigh;
    if((_lHighTimer > 100)) {
      if(_bDimmerMode == LOW) { 
        Serial.println("Dimmer ON");
        _bDimmerMode = HIGH;
        _iPulse = 0;
        digitalWrite(GREEN_LED, HIGH);
//        kaKuTransmitter.sendSignal(_housecode, _unit_number, true);
      }
    } 
  }

  if(_iTotal == 0) {
    _bCurState = LOW;
    _lTimeLow = _lTimer;
    _lLowTimer = _lTimer - _lTimeLow;
    if (_bDimmerMode == HIGH) {
      _bDimmerMode = LOW;
      digitalWrite(GREEN_LED, LOW);
//      kaKuTransmitter.sendSignal(_housecode, _unit_number, true);
    }
    if (((_lTimer - _lTimeHigh) > 300) && (_iPulse > 0)){
      switch(_iPulse){
      case 1:
//        kaKuTransmitter.sendSignal(_housecode, _unit_number, true);
        break;
      case 2:
//        kaKuTransmitter.sendSignal(_housecode, _unit_number, false);
        break;
      }    
      _iPulse = 0;
    }
    if((_lLowTimer % _iLowPulse) == 0) {
      if(_bCurState != _bPrevState) {
        _bPrevState = _bCurState;
        digitalWrite(RED_LED,LOW); // Light the led
      }        
    }
  }
}
touchDimmer test = touchDimmer('N',15,10);
touchDimmer test2 = touchDimmer('N',15,9);
void setup() {
  pinMode(RED_LED, OUTPUT); 
  pinMode(GREEN_LED, OUTPUT);
  digitalWrite(GREEN_LED, LOW);
  digitalWrite(RED_LED, LOW);
  test.begin();
  test2.begin();
}
void loop() {
  test.check();
  test2.check();
} 

Share this post


Link to post
Share on other sites

Also avoid floats all together. The MSP430 does not have an FPU so it will need to emulate it which results in a lot of overhead when doing math on floating point variables.

Share this post


Link to post
Share on other sites

You take 10 measurements, but store this in a variable, while it is constant.

If you measure over a power of 2 (2, 4, 8, 16, etc) you can use shifting instead of dividing to obtain the average.

Share this post


Link to post
Share on other sites

Thanks. Already removed the float because I didn't really need it. The above code still contains a bug. I will post the new code once I am home.

 

I remember reading somewhere that the modulo function also cause problems. Is that true?

 

Sent from my HTC One using Tapatalk

 

 

Share this post


Link to post
Share on other sites

Here is the new code.

I haven't got many experience with coding so please let me know if (and where) there is room for improvement.

#include <RemoteTransmitter.h>
#include <CapTouch.h>
//#include <DHT.h>
//#include <SensorTransmitter.h>
//#include <x10rf.h>

// Time and stuff
#define readings 10 
#define HighPulse 10 
#define LowPulse 10
#define pulsetimeout 200
#define dimmermode 100
#define interval = 3000

// Hardware pins
#define DHTPIN 12     
#define OOKPIN 11 
#define BUT1PIN 10
#define BUT2PIN 9

// Other
#define DHTTYPE DHT11

// Initialisation of lib's
//DHT dht(DHTPIN, DHTTYPE);
KaKuTransmitter kaKuTransmitter(OOKPIN,280,4);
//ThermoHygroTransmitter transmitter(OOKPIN, 0, 1);
//x10rf myx10 = x10rf(OOKPIN,0,1);

//unsigned long previousMillis = 0;
boolean busy = false;

#ifndef touchDimmer_h
#define touchDimmer_h
class touchDimmer {
public:
  touchDimmer(char housecode, byte unit_number, byte pin);
  void begin();
  void check();
private:
  unsigned long _lTimeHigh;
  unsigned long _lHighTimer;
  unsigned long _lLowTimer;
  unsigned long _lTimeLow;
  unsigned long _lTimer;
  int _iPulse;
  int _iReadings[readings];      // the readings from the analog input
  int _iIndex;                  // the index of the current reading
  int _iTotal;                  // the running total
  boolean _bCurState;
  boolean _bPrevState;
  boolean _bDimmerMode;
  boolean _bButtonState;
  boolean _bOnOffState;
  byte _housecode;
  byte _unit_number;
  byte _pin;
  CapTouch button;
};
#endif

touchDimmer::touchDimmer(char housecode, byte unit_number, byte pin) 
: 
_housecode(housecode)
,_unit_number(unit_number)
, _pin(pin)
,button(CapTouch(_pin,TOUCH_BUTTON))
{
}

void touchDimmer::begin()
{
  _lTimeHigh = 0;
  _lHighTimer = 0;
  _lLowTimer = 0;
  _lTimeLow = 0;
  _lTimer = 0;
  _iPulse = 0;
  // _iNumReadings = readings;
  _iReadings[readings];
  _iIndex = 0;      
  _iTotal = 0;         
  //_average = 0;         
  _bCurState = false;
  _bPrevState = false;
  _bDimmerMode = false;
  _bButtonState = false;
  _bOnOffState = false;
  for (int thisReading = 0; thisReading < readings; thisReading++) {
    _iReadings[thisReading] = 0;
  }
  kaKuTransmitter.sendSignal(_housecode, _unit_number, false);
};

void touchDimmer::check()
{
  _lTimer = millis();
  _iTotal= _iTotal - _iReadings[_iIndex];  
  _iReadings[_iIndex] = button.isTouched();
  _iTotal= _iTotal + _iReadings[_iIndex]; 
  _iIndex = _iIndex + 1;
  if (_iIndex >= readings)              
    _iIndex = 0;                           
  if(_iTotal == readings) {
    _bCurState = HIGH;
    if(_bCurState != _bPrevState) {
      _lTimeHigh = _lTimer;
      digitalWrite(RED_LED,HIGH);
      if((_lHighTimer % HighPulse) == 0) {
        if(_bCurState != _bPrevState) {
          _iPulse++;
          _bPrevState = _bCurState;
          digitalWrite(RED_LED,HIGH);
        }     
      }     
    }
    _lHighTimer = _lTimer - _lTimeHigh;
    if((_lHighTimer > dimmermode)) {
      busy = true;
      if(_bDimmerMode == LOW) { 
        _bDimmerMode = HIGH;
        _iPulse = 0;
        digitalWrite(GREEN_LED, HIGH);
        if (_bOnOffState == true) {
          kaKuTransmitter.sendSignal(_housecode, _unit_number, true);
          //_bOnOffState = true;
        } 
      }
      busy = false;
    } 
  }
  if(_iTotal == 0) {
    _bCurState = LOW;
    _lTimeLow = _lTimer;
    _lLowTimer = _lTimer - _lTimeLow;
    if (_bDimmerMode == HIGH) {
      _bDimmerMode = LOW;
      digitalWrite(GREEN_LED, LOW);
      if (_bOnOffState == true) {
        kaKuTransmitter.sendSignal(_housecode, _unit_number, true);
      }      
    }
    if (((_lTimer - _lTimeHigh) > pulsetimeout) && (_iPulse > 0)){
      busy = true;
      switch(_iPulse){
      case 1:
        if(_bOnOffState == false) {
          kaKuTransmitter.sendSignal(_housecode, _unit_number, true);
          _bOnOffState = true;
        }
        else
        {
          kaKuTransmitter.sendSignal(_housecode, _unit_number, false); 
          _bOnOffState = false;        
        }
        break;
      case 3:
        //myx10.x10Switch('D',15,0); // Switch D15 off
        tone(13, 250, 100);
        kaKuTransmitter.sendSignal('N', 8, false); 
        break;
      default:
        break;
      }    
      _iPulse = 0;
      busy = false;
    }
    if((_lLowTimer % LowPulse) == 0) {
      if(_bCurState != _bPrevState) {
        _bPrevState = _bCurState;
        digitalWrite(RED_LED,LOW); // Light the led
      }        
    }
  }
}

touchDimmer test = touchDimmer('N',1,BUT1PIN);
//touchDimmer test2 = touchDimmer('N',14,BUT2PIN);

void setup() {
  pinMode(RED_LED, OUTPUT); 
  pinMode(GREEN_LED, OUTPUT);
  digitalWrite(GREEN_LED, LOW);
  digitalWrite(RED_LED, LOW);
  test.begin();
  //test2.begin();
  //  dht.begin();
  //  myx10.begin();
}

void loop() {
  //unsigned long currentMillis = millis();
  test.check();

} 

Share this post


Link to post
Share on other sites

sort of. The code works but after sometimes it gets stuck and becomes unresponsive.

Not sure what is going. I suspect it has something to do with the readings for the touchsensor. I noticed that some powersupplies can cause strange behaviour with the captouch library.

 

 

You can find a demo here: https://plus.google.com/108520609225955114785/posts/NXZhE3f3NtJ

 

I have added lights to an Ikea shelf along with a wireless dimmer.

Then I attached a strip of aluminum to my bed which is used as the touch sensor.

Share this post


Link to post
Share on other sites

For the transmission side I use a 433Mhz OOK FSK transmitter:

 

433MHz-Wireless-Transmitter-Module-Super

The receiving end is a wireless dimmer sold by http://www.klikaanklikuit.nl. I believe this is sold as "HomeEasy" in other parts of the world.

 

I am still having problems with the code. The MCU freezes(red and green led on) after some time. Is it possible that my sketch is causing a RAM-overflow after some time? Not sure how to debug this  :angry:

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×