Adding 4th dimmer. Struggle.



  • Had a code which was working for a long time. Decided to add another dimmer. And now having hard time. Seems to work light switches on - then never goes off. One dimmer is on 100% of the time. Any help much appreciated. Added comments on changed lines //ADDED
    Guess screwed up with currentLevel but not sure

    #define SN "MYS Kitchen Hood"
    #define SV "2.1"
    
    //System settings
    #define MY_RADIO_NRF24
    #define MY_RF24_CE_PIN 8 //ADDED
    
    
    // Include all the libraries
    #include <MySensors.h> 
    #include <SPI.h>
    #include <DHT.h> 
    #include <math.h>
    #include <Wire.h>
    #include <Bounce2.h>
    
    #define MY_NODE_ID 71
    
    //DEFINE CHILD_IDS
    #define DIMMER_NODE_1 0
    #define DIMMER_NODE_2 1
    #define DIMMER_NODE_3 2
    #define DIMMER_NODE_4 3 //ADDED
    #define CHILD_ID_HUM 4
    #define CHILD_ID_TEMP 5
    #define CHILD_ID_MQ 6
    #define CHILD_BUT1 7
    #define CHILD_BUT2 8
    #define CHILD_BUT3 9
    #define CHILD_BUT4 10
    //BUTTONS
    #define BUTTON_PIN1  A0
    #define BUTTON_PIN2  A1
    #define BUTTON_PIN3  A2
    #define BUTTON_PIN4  A3
    //SENSORS
    #define DHT_PIN 8
    const int MQ_Pin = A4;
    //DIMMER
    #define LED_PIN_1 3
    #define LED_PIN_2 5
    #define LED_PIN_3 6
    #define LED_PIN_4 9 //ADDED
    #define FADE_DELAY 5
    
    DHT dht;
    
    //BUTTONS
    Bounce debouncer_1 = Bounce(); 
    Bounce debouncer_2 = Bounce();
    Bounce debouncer_3 = Bounce();
    Bounce debouncer_4 = Bounce();
    int oldValue_1=-1;
    int oldValue_2=-1;
    int oldValue_3=-1;
    int oldValue_4=-1;
    bool state1;
    bool state2;
    bool state3;
    bool state4;
    MyMessage msgbut1(CHILD_BUT1,V_STATUS);
    MyMessage msgbut2(CHILD_BUT2,V_STATUS);
    MyMessage msgbut3(CHILD_BUT3,V_STATUS);
    MyMessage msgbut4(CHILD_BUT4,V_STATUS);
    //SENSORS
    float lastTemp;
    float lastHum;
    float hum_floa;
    float last_mq_reading;
    long Millis = 0;
    long Millis_interval = 30000;
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgMQ(CHILD_ID_MQ, V_LEVEL);
    //DIMMER
    //byte currentLevel[3] = {0,0,0};
    byte currentLevel[4] = {0,0,0,0}; //added
    MyMessage dimmerMsg0(0, V_PERCENTAGE);
    MyMessage lightMsg0(0, V_STATUS);
    MyMessage dimmerMsg1(1, V_PERCENTAGE);
    MyMessage lightMsg1(1, V_STATUS);
    MyMessage dimmerMsg2(2, V_PERCENTAGE);
    MyMessage lightMsg2(2, V_STATUS);
    MyMessage dimmerMsg3(3, V_PERCENTAGE); //ADDED
    MyMessage lightMsg2(3, V_STATUS); //ADDED
    
    void before() 
    {
      dht.setup(DHT_PIN);
      analogWrite( LED_PIN_1, 0); 
      analogWrite( LED_PIN_2, 0);
      analogWrite( LED_PIN_3, 0);
      analogWrite( LED_PIN_4, 0); //ADDED
      pinMode(BUTTON_PIN1,INPUT);
      digitalWrite(BUTTON_PIN1, HIGH);
      pinMode(BUTTON_PIN2,INPUT);
      digitalWrite(BUTTON_PIN2, HIGH);
      pinMode(BUTTON_PIN3,INPUT);
      digitalWrite(BUTTON_PIN3, HIGH);
      pinMode(BUTTON_PIN4,INPUT);
      digitalWrite(BUTTON_PIN4, HIGH);
      debouncer_1.attach(BUTTON_PIN1);
      debouncer_1.interval(5);
      debouncer_2.attach(BUTTON_PIN2);
      debouncer_2.interval(5);
      debouncer_3.attach(BUTTON_PIN3);
      debouncer_3.interval(5);
      debouncer_4.attach(BUTTON_PIN4);
      debouncer_4.interval(5);
    }
    void setup() 
    { }
    
    void presentation()  
    { 
      sendSketchInfo(SN, SV);
      present(CHILD_ID_HUM, S_HUM);
      present(CHILD_ID_TEMP, S_TEMP);
      present(CHILD_ID_MQ, S_AIR_QUALITY);  
    
      present( DIMMER_NODE_1, S_DIMMER );
      send(dimmerMsg0.set(0));
      present( DIMMER_NODE_2, S_DIMMER );
      send(dimmerMsg1.set(0));
      present( DIMMER_NODE_3, S_DIMMER );
      send(dimmerMsg2.set(0));
      present( DIMMER_NODE_4, S_DIMMER ); //ADDED
      send(dimmerMsg3.set(0)); //ADDED
      present(CHILD_BUT1, S_BINARY);
      present(CHILD_BUT2, S_BINARY);
      present(CHILD_BUT3, S_BINARY);
      present(CHILD_BUT4, S_BINARY);
    }
    
    void loop() 
    {
      int value_but_1 = debouncer_1.read();
      int value_but_2 = debouncer_2.read();
      int value_but_3 = debouncer_3.read();
      int value_but_4 = debouncer_4.read(); 
    //DHT+MQ
    unsigned long Current_Millis = millis();
    if((unsigned long)(Current_Millis - Millis) >= Millis_interval)
      {
      Millis = Current_Millis; 
      delay(dht.getMinimumSamplingPeriod());
      float temperature = dht.getTemperature();
      float humidity = dht.getHumidity();
      float mq_reading = analogRead(MQ_Pin);
        
        if (isnan(temperature)) 
          {Serial.println("Failed reading temperature from DHT");} 
        if (isnan(humidity)) 
          {Serial.println("Failed reading humidity from DHT");} 
        if (isnan(mq_reading)) 
          { Serial.println("Failed mq_reading"); } 
    
        else 
        {
          send(msgTemp.set(temperature, 1));
          send(msgHum.set(humidity, 1));
          send(msgMQ.set(mq_reading, 1));
        }
      }
    //BUTTONS
      debouncer_1.update();
      if (value_but_1 != oldValue_1) 
      { 
      if ( value_but_1==0)
        {
        state1 = !state1;
        send(msgbut1.set(state1));
        }
      oldValue_1 = value_but_1;
      }
      debouncer_2.update();
      if (value_but_2 != oldValue_2) 
      { 
      if ( value_but_2==0)
        {
        state2 = !state2;
        send(msgbut2.set(state2));
        }
      oldValue_2 = value_but_2;
      }
      debouncer_3.update();
      if (value_but_3 != oldValue_3) 
      { 
        if ( value_but_3==0)
        {
        state3 = !state3;
        send(msgbut3.set(state3));
        }
      oldValue_3 = value_but_3;
      }
      debouncer_4.update();
      if (value_but_4 != oldValue_4) 
      { 
        if ( value_but_4==0)
        {
        state4 = !state4;
        send(msgbut4.set(state4));
        }
      oldValue_4 = value_but_4;
      }
    }
    //DIMMER
    void receive(const MyMessage &message) 
    {
      if (message.type == V_STATUS || message.type == V_PERCENTAGE)
      {
        int requestedLevel = atoi( message.data );
        requestedLevel *= ( message.type == V_STATUS ? 100 : 1 );
        requestedLevel = requestedLevel > 100 ? 100 : requestedLevel;
        requestedLevel = requestedLevel < 0   ? 0   : requestedLevel;
        fadeToLevel( requestedLevel, message.sensor);
          switch(message.sensor)
        {
        case 0:
          send(lightMsg0.set(currentLevel[0] > 0 ? 1 : 0));
          send( dimmerMsg0.set(currentLevel[0]) );
        break;
        case 1:
          send(lightMsg1.set(currentLevel[1] > 0 ? 1 : 0));
          send( dimmerMsg1.set(currentLevel[1]) );
        break;
        case 2:
          send(lightMsg2.set(currentLevel[2] > 0 ? 1 : 0));
          send( dimmerMsg2.set(currentLevel[2]) );
        break; 
        //ADDED CASE 3
        case 3:
          send(lightMsg3.set(currentLevel[3] > 0 ? 1 : 0));
          send( dimmerMsg3.set(currentLevel[3]) );
        break;  
        }
        }
    }
    void fadeToLevel( int toLevel, byte sensorId ) 
    {
      int delta = ( toLevel - currentLevel[sensorId] ) < 0 ? -1 : 1;
      while ( currentLevel[sensorId] != toLevel )
      {
        currentLevel[sensorId] += delta;
        switch(sensorId)
        {
        case 0:
          analogWrite( LED_PIN_1, (int)(currentLevel[sensorId] / 100. * 255) );
        break;
        case 1:
          analogWrite( LED_PIN_2, (int)(currentLevel[sensorId] / 100. * 255) );  
        break;
        case 2:
          analogWrite( LED_PIN_3, (int)(currentLevel[sensorId] / 100. * 255) );
        break; 
        //ADDED CASE3
        case 3:
          analogWrite( LED_PIN_4, (int)(currentLevel[sensorId] / 100. * 255) );
        break;           
        }
      delay( FADE_DELAY );
      }
    }
    

  • Contest Winner

    Its probably a good time to start learning about arrays.



  • @BulldogLowell Read about them. But still seems i address the array correctly. Or i'm wrong?


  • Contest Winner

    @moskovskiy82

    Sorry, I meant that your code could be extremely simplified by using arrays.

    Yours is a good example of how it is much harder to refactor in the case (like yours) where you simply need to add one more of some object.

    things like this can be problematic:

    #define DIMMER_NODE_1 0
    #define DIMMER_NODE_2 1
    #define DIMMER_NODE_3 2
    #define DIMMER_NODE_4 3 //ADDED
    

    where 1 = 0, 2 = 1, etc.... it is not very intuitive

    I cannot find the problem in your code... are you sure you are wired up correctly?



  • Well after much trial and error - seems that pin5 is behaving erratically. Don't know why. Rewired to an external dimmer board. Changed arduinos. Nothing helps which is extremly strange



  • Just out of curiosity, Is there a standard dimmer module you are using or is it custom made?

    Hope you have checked the current being supplied since that is limited. The current (signal) amplifier configuration on the dimmer module may be an issue if not designed for low current signals (especially if there are multiple parts attached to the same arduino).



  • @moskovskiy82 You may at least have to chang this:

    MyMessage lightMsg2(2, V_STATUS);
    MyMessage dimmerMsg3(3, V_PERCENTAGE); //ADDED
    MyMessage lightMsg2(3, V_STATUS); //ADDED
    

    The second imo should be lightMsg3...

    I completely agree with @BulldogLowell : Better use arrays for nodes like yours. Good example: https://forum.mysensors.org/topic/4847/multi-button-relay-sketch/33#


  • Contest Winner

    @rejoe2 said in Adding 4th dimmer. Struggle.:

    I completely agree with @BulldogLowell : Better use arrays for nodes like yours. Good example: https://forum.mysensors.org/topic/4847/multi-button-relay-sketch/33#

    and I don't like the blocking nature of the fading. that should be refactored.

    plus, the fyi the Bounce2 library has another constructor which sets pinMode...
    instead of this:

      pinMode(BUTTON_PIN1,INPUT);
      digitalWrite(BUTTON_PIN1, HIGH);
    
    //...
    debouncer_1.attach(BUTTON_PIN1);
      debouncer_1.interval(5);
    

    just this:

    debouncer_1.attach(BUTTON_PIN1, INPUT_PULLUP);
    debouncer_1.interval(5);
    

    i'll post an alternative if I get the chance...


  • Contest Winner

    I can't test this but something like:

    #define SN "Four Fader Test"
    #define SV "0.1a"
    
    #define NUMBER_OF_DIMMERS 4
    
    //System settings
    #define MY_RADIO_NRF24
    #define MY_RF24_CE_PIN 8 //ADDED
    #define MY_NODE_ID 71
    
    #include <MySensors.h>
    #include <SPI.h>
    #include "Fade.h"
    
    MyMessage dimmer[NUMBER_OF_DIMMERS];
    MyMessage light[NUMBER_OF_DIMMERS];
    
    Fade fader[NUMBER_OF_DIMMERS];
    byte leds[NUMBER_OF_DIMMERS] = {3, 5, 6, 9};
    
    void before()
    {
      int i = 0;
      for (auto fdr : fader)
      {
        fdr = Fade(leds[i++], 10, 0, 255, MILLIS_TIMER); // led speed 5 milliseconds/step; pwm at 0 min and 255 max  (MILLIS_TIMER)
        fdr.begin();
      }
      i = 0;
      for (auto msg : dimmer)
        msg = MyMessage(i++, S_DIMMER);
      i = 0;
      for (auto msg : light)
        msg = MyMessage(i++, S_BINARY);
    }
    void presentation()
    {
      sendSketchInfo(SN, SV);
      int i = 0;
      for (auto d : dimmer)
        present(i++, S_DIMMER);
    }
    
    void setup()
    {
      Serial.begin(9600);
      Serial.println(F("Setup Complete..."));
    }
    
    void loop()
    {
      uint32_t currentMillis = millis();
      for (auto fdr : fader)
        fdr.update(currentMillis);
    }
    
    void receive(const MyMessage &message)
    {
      if (message.type == V_STATUS || message.type == V_PERCENTAGE)
      {
        int requestedLevel = atoi(message.data);
        if (message.type == V_STATUS)
          requestedLevel = requestedLevel ? 100 : 0;
        else
          requestedLevel = constrain(requestedLevel, 0, 100);
        fader[message.sensor].setTarget(map(requestedLevel, 0, 100, 0, 255));
        send(light[message.sensor].set(requestedLevel > 0 ? 1 : 0));
        send(dimmer[message.sensor].set(requestedLevel));
      }
    }
    

    I used my non-blocking Fade.h:

    #ifndef Fade_h
    #define Fade_h
    
    #include <Arduino.h>
    
    enum timer{
      MILLIS_TIMER, 
      MICROS_TIMER
    };
    
    class Fade
    {
      public:
        Fade() {};
        Fade(int pin, uint32_t timeStep = 15, uint8_t minVal = 0, uint8_t maxVal = 255, timer timerSelect = MILLIS_TIMER);
        void begin(); 
        void setTarget(int to);
        void update();
        void update(uint32_t time);
        uint8_t getMin();
        uint8_t getMax();
        uint8_t getCurrent();
        uint32_t readSpeed();
        uint32_t writeSpeed(uint32_t time);
        uint8_t getSetpoint();
      private:
        uint8_t _min;
        uint8_t _max;
        uint8_t _targetFade;
        uint8_t _pwmRate;
        uint32_t _time;
        uint32_t _last;
        uint8_t _pin;
        bool _microsTimer;
    };
    
    #endif
    

    and my Fade.cpp:

    
    #include "Fade.h"
    #include <Arduino.h>
    
    Fade::Fade(int pin, uint32_t timeStep, uint8_t minVal, uint8_t maxVal, timer timerSelect)
    {
      _pin = pin;
      _time = timeStep;
      _min = minVal;
      _max = maxVal;
      analogWrite(_pin, _min);
      _pwmRate = _min;
      _microsTimer = timerSelect;
    }
    
    void Fade::begin()
    {
      analogWrite(_pin, _min);
    }
    
    void Fade::setTarget(int to)
    {
      _targetFade = (uint8_t) constrain(to, _min, _max);
    
      this->update();
    }
    
    void Fade::update()
    {
      this->update(_microsTimer? micros() : millis());
    }
    
    void Fade::update(uint32_t time)
    {
      if (time - _time > _last)
      {
        _last = time;
        if (_pwmRate > _targetFade) analogWrite(_pin, --_pwmRate);
        if (_pwmRate < _targetFade) analogWrite(_pin, ++_pwmRate);
      }
    }
    
    uint8_t Fade::getSetpoint()
    {
      return _targetFade;
    }
    
    uint8_t Fade::getCurrent()
    {
      return _pwmRate;
    }
    
    uint32_t Fade::readSpeed()
    {
      return _time;
    }
    
    uint32_t Fade::writeSpeed(uint32_t time)
    {
      _time = time;
    }
    
    uint8_t Fade::getMin()
    {
      return _min;
    }
    
    uint8_t Fade::getMax()
    {
      return _max;
    }
    
    

Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.