p2baron 11 Posted December 6, 2013 Share Posted December 6, 2013 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(); } Quote Link to post Share on other sites
roadrunner84 466 Posted December 6, 2013 Share Posted December 6, 2013 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. p2baron and energia 2 Quote Link to post Share on other sites
p2baron 11 Posted December 6, 2013 Author Share Posted December 6, 2013 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. 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(); } Quote Link to post Share on other sites
energia 485 Posted December 7, 2013 Share Posted December 7, 2013 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. Quote Link to post Share on other sites
roadrunner84 466 Posted December 7, 2013 Share Posted December 7, 2013 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. Quote Link to post Share on other sites
p2baron 11 Posted December 9, 2013 Author Share Posted December 9, 2013 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 Quote Link to post Share on other sites
p2baron 11 Posted December 9, 2013 Author Share Posted December 9, 2013 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(); } Quote Link to post Share on other sites
energia 485 Posted December 10, 2013 Share Posted December 10, 2013 Is the code posted above working as expected or do you still have issues with it? Quote Link to post Share on other sites
p2baron 11 Posted December 13, 2013 Author Share Posted December 13, 2013 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. Quote Link to post Share on other sites
energia 485 Posted December 14, 2013 Share Posted December 14, 2013 That's pretty awesome project! What are you using for the Wireless side? Ziet er naar uit dat dat klikaanklikuit spul steed populairder word in Europa. Quote Link to post Share on other sites
p2baron 11 Posted December 16, 2013 Author Share Posted December 16, 2013 For the transmission side I use a 433Mhz OOK FSK transmitter: 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 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.