Navigation

    • Register
    • Login
    • Search
    • OpenHardware.io
    • Categories
    • Recent
    • Tags
    • Popular
    1. Home
    2. maghac
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    maghac

    @maghac

    41
    Reputation
    104
    Posts
    1162
    Profile views
    0
    Followers
    0
    Following
    Joined Last Online

    maghac Follow

    Best posts made by maghac

    • RGB LED strip

      I built a RGB LED strip controllable via mysensor, based on a 12V RGB LED strip and three IRF540 MOSFETs. The arduino is a 5V pro mini clone that I feed with 12V on the RAW pin.

      I followed the guide on https://learn.adafruit.com/rgb-led-strips/usage for wiring the MOSFETS and the LED strip. I used the Newbie PCB by @sundberg84 for holding the arduino and the radio, but put the MOSFETs on a separate prototyping board (maybe next time I'll try to solder them to the prototyping area of the Newbie PCB).

      I implemented a fading feature in the sketch, so it can fade slowly between colors or on/off. The speed is controlled by sending a V_VAR1 message with the speed (typical value could be around 200-300 for a nice effect). Speed = 0 means fading is off.

      Here is the code:

      /**
       * This program is free software; you can redistribute it and/or
       * modify it under the terms of the GNU General Public License
       * version 2 as published by the Free Software Foundation.
       *
       * LED STRIP sketch for Mysensors
       *******************************
       *
       * REVISION HISTORY
       * 1.0 
       *   Based on the example sketch in mysensors
       * 1.1
       *   fadespeed parameter (send as V_VAR1 message)
       *   HomeAssistant compatible (send status to ack)
       */
      
      #define MY_OTA_FIRMWARE_FEATURE
      #define MY_NODE_ID AUTO
      
      #define MY_RADIO_NRF24
      
      #include <MySensors.h>
      
      #define CHILD_ID_LIGHT 1
      
      #define SN "LED Strip"
      #define SV "1.1"
      
      MyMessage lightMsg(CHILD_ID_LIGHT, V_LIGHT);
      MyMessage rgbMsg(CHILD_ID_LIGHT, V_RGB);
      MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER);
      
      byte red = 255;
      byte green = 255;
      byte blue = 255;
      byte r0 = 255;
      byte g0 = 255;
      byte b0 = 255;
      char rgbstring[] = "ffffff";
      
      int on_off_status = 0;
      int dimmerlevel = 100;
      int fadespeed = 0;
      
      #define REDPIN 6
      #define GREENPIN 5
      #define BLUEPIN 3
      
      void setup()
      {
        // Fix the PWM timer. Without this the LEDs will flicker.
        TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00);
      
        // Output pins
        pinMode(REDPIN, OUTPUT);
        pinMode(GREENPIN, OUTPUT);
        pinMode(BLUEPIN, OUTPUT);
        
      }
      
      void presentation()
      {
      	// Send the Sketch Version Information to the Gateway
      	sendSketchInfo(SN, SV);
      	present(CHILD_ID_LIGHT, S_RGB_LIGHT);
      }
      
      void loop()
      {
        static bool first_message_sent = false;
        if ( first_message_sent == false ) {
          Serial.println( "Sending initial state..." );
          set_hw_status();
          send_status();
          first_message_sent = true;
        }
      }
      
      void receive(const MyMessage &message)
      {
        int val;
        
      	if (message.type == V_RGB) {
      		Serial.println( "V_RGB command: " );
          Serial.println(message.data);
          long number = (long) strtol( message.data, NULL, 16);
      
          // Save old value
          strcpy(rgbstring, message.data);
          
          // Split it up into r, g, b values
          red = number >> 16;
          green = number >> 8 & 0xFF;
          blue = number & 0xFF;
      
          send_status();
          set_hw_status();
      
      	} else if (message.type == V_LIGHT || message.type == V_STATUS) {
          Serial.println( "V_LIGHT command: " );
          Serial.println(message.data);
          val = atoi(message.data);
          if (val == 0 or val == 1) {
            on_off_status = val;
            send_status();
            set_hw_status();
          }
          
        } else if (message.type == V_DIMMER || message.type == V_PERCENTAGE) {
          Serial.print( "V_DIMMER command: " );
          Serial.println(message.data);
          val = atoi(message.data);
          if (val >= 0 and val <=100) {
            dimmerlevel = val;
            send_status();
            set_hw_status();
          }
          
        } else if (message.type == V_VAR1 ) {
          Serial.print( "V_VAR1 command: " );
          Serial.println(message.data);
          val = atoi(message.data);
          if (val >= 0 and val <= 2000) {
            fadespeed = val;
          }
          
      	} else {
      		Serial.println( "Invalid command received..." );
      		return;
      	}
      
      }
      
      void set_rgb(int r, int g, int b) {
        analogWrite(REDPIN, r);
        analogWrite(GREENPIN, g);
        analogWrite(BLUEPIN, b);
      }
      
      void set_hw_status() {
        int r = on_off_status * (int)(red * dimmerlevel/100.0);
        int g = on_off_status * (int)(green * dimmerlevel/100.0);
        int b = on_off_status * (int)(blue * dimmerlevel/100.0);
      
        if (fadespeed >0) {
          
          float dr = (r - r0) / float(fadespeed);
          float db = (b - b0) / float(fadespeed);
          float dg = (g - g0) / float(fadespeed);
          
          for (int x = 0;  x < fadespeed; x++) {
            set_rgb(r0 + dr*x, g0 + dg*x, b0 + db*x);
            delay(100);
          }
        }
      
        set_rgb(r, g, b);
       
        r0 = r;
        b0 = b;
        g0 = g;
        
      }
      
      
      void send_status() {
        send(rgbMsg.set(rgbstring));
        send(lightMsg.set(on_off_status));
        send(dimmerMsg.set(dimmerlevel));
      }
      

      I have a MQTT gateway and I can turn the strip on, set the color to pink and fade speed to 500 by the following commands:

      mosquitto_pub -t mysensors-in/240/1/1/0/40 -m ff6060
      mosquitto_pub -t mysensors-in/240/1/1/0/24 -m 500
      mosquitto_pub -t mysensors-in/240/1/1/0/2 -m 1
      

      A couple of pics:

      0_1493844732314_File_000 (4).jpeg
      0_1493844743322_File_001.jpeg

      posted in My Project
      maghac
      maghac
    • RE: What did you build today (Pictures) ?

      I built a lithophane lamp for my grandson. The electronics is basically only a pro mini and 36 neopixels. Sadly this version is not mysensorized but maybe I'll do that in version 2 🙂

      0_1511962986127_IMG_8296.jpg
      0_1511963011727_IMG_8301.jpg
      0_1511963026597_IMG_8297.jpg
      0_1511963045498_IMG_8298.jpg

      posted in General Discussion
      maghac
      maghac
    • RE: RGB LED strip

      I'd thought I'd share a pic now that the led strip has been mounted. Unfortunately the iphone camera doesn't have enough dynamic range to capture the light correctly - it looks a lot better in reality!

      Through some HomeAssistant/tellstick magic I can also turn it on and off using a normal 433Mhz remote instead of having to send MQTT messages from the command line. This increased the WAF considerably 🙂

      0_1494318228883_File_000.jpeg

      posted in My Project
      maghac
      maghac
    • RE: What did you build today (Pictures) ?

      @gohan said in What did you build today (Pictures) ?:

      I have seen a video where you can convert your pictures and print them using a 3D printer

      Correct, these are 3D printed lithophanes (https://en.wikipedia.org/wiki/Lithophane). I used http://3dp.rocks/lithophane/ to convert jpg files to STL files for printing.

      posted in General Discussion
      maghac
      maghac
    • RE: RGB LED strip

      Well, it took some time, but here is v1.8 at last!

      I have modified the code to handle RGBW strips, since I realized that the white light from RGB strips is very uncomfortable and not really suitable for general illumination. It should be fairly easy to convert it back to RGB though. Adding the W channel means that I now need 4 PWM pins, and therefore it was necessary to redefine one of the pins that the radio is connected to - the sketch now expects CE to be connected to pin 8 instead of 9 which is the default (a pro mini only has 3 free PWM pins if you use the default setup).

      I've also completely changed now programs/modes are implemented so it should be easier to add new programs. Feel free to experiment with this and let me know what you think.

      /**
       * This program is free software; you can redistribute it and/or
       * modify it under the terms of the GNU General Public License
       * version 2 as published by the Free Software Foundation.
       *
       * LED STRIP sketch for Mysensors
       *******************************
       *
       * REVISION HISTORY
       * 1.0 
       *   Based on the example sketch in mysensors
       * 1.1
       *   prgspeed parameter (send as V_VAR1 message)
       *   HomeAssistant compatible (send status to ack)
       * 1.2
       *   OTA support
       * 1.3
       *   Power-on self test
       * 1.4
       *   Bug fix
       * 1.5
       *   Other default values
       * 1.6
       *   Repeater feature
       * 1.7
       *   Multitasking. Alarm and RELAX modes.
       * 1.8
       *   Reengineered programs/modes logic.
       *   RGBW variant. Requires 4 PWM pins, so we need to move use a different pin for one of radio connections.
       */
      
      #define MY_OTA_FIRMWARE_FEATURE
      // #define MY_REPEATER_FEATURE
      #define MY_NODE_ID AUTO
      
      #define MY_RADIO_NRF24
      
      //#define MY_DEBUG
      
      // Normally the radio uses pin 9 for CE
      #define MY_RF24_CE_PIN  8
      
      #include <MySensors.h>
      
      #define CHILD_ID_LIGHT 1
      
      #define SN "LED Strip"
      #define SV "1.8"
      
      MyMessage lightMsg(CHILD_ID_LIGHT, V_LIGHT);
      MyMessage rgbwMsg(CHILD_ID_LIGHT, V_RGBW);
      MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER);
      MyMessage prgspeedMsg(CHILD_ID_LIGHT, V_VAR1);
      MyMessage programMsg(CHILD_ID_LIGHT, V_VAR2);
      
      #define RR 0
      #define GG 1
      #define BB 2
      #define WW 3
      
      byte current[] = {255, 255, 255, 255};
      byte target[] = {255, 255, 255, 255};
      byte save[] = {0, 0, 0, 0};
      byte temp[] = {0, 0, 0, 0};
      
      float delta[] = {0.0, 0.0, 0.0, 0.0};
      
      char rgbwstring[] = "000000ff";
      
      int on_off_status = 0;
      int dimmerlevel = 100;
      int prgspeed = 20;
      unsigned long last_update = 0;
      unsigned long tick_length = 5;
      int fade_step = 0;
      
      int program_timer;
      int program_cycle;
      int program_step;
      
      // Make sure these are PWM pins
      #define REDPIN 6
      #define GREENPIN 5
      #define BLUEPIN 3
      #define WHITEPIN 9
      
      #define LIGHT_NORMAL 0
      #define LIGHT_FADING 1
      
      #define PROGRAM_NOP 0
      
      int light_mode = LIGHT_NORMAL;
      int program_mode = PROGRAM_NOP;
      
      #define SET 0    
      #define SET_AND_WAIT 1    
      #define SET_RANDOM 2
      #define SET_RANDOM_AND_WAIT 3
      #define FADE 4
      #define FADE_RANDOM 5
      #define WAIT 6
      
      typedef struct rgb_cmd {
        byte cmd;
        int p;
        byte rgbw[4];
      } rgb_cmd;
      
      rgb_cmd program_ALARM[] = {
        {SET_AND_WAIT, 25, {255, 255, 255, 0}},
        {SET_AND_WAIT, 25, {0, 0, 0, 0}},
        {SET_AND_WAIT, 25, {0, 0, 0, 255}},
        {SET_AND_WAIT, 25, {0, 0, 0, 0}}
      };
      
      rgb_cmd program_RELAX[] = {
        {FADE, 1000, {255, 32, 0, 0}},
        {FADE, 1000, {255, 32, 16, 0}},
        {FADE, 1000, {255, 16, 32, 0}},
        {FADE, 1000, {255, 128, 0, 0}},
        {FADE, 1000, {255, 32, 0, 0}},
        {FADE, 1000, {255, 32, 32, 0}},
        {FADE, 1000, {255, 0, 32, 0}}
      };
      
      rgb_cmd program_PARTY[] = {
        {SET_AND_WAIT, 10, {255, 0, 0, 0}},
        {SET_AND_WAIT, 10, {0, 0, 0, 255}},
        {SET_AND_WAIT, 10, {255, 0, 0, 0}},
        {SET_AND_WAIT, 10, {0, 0, 0, 255}},
        {SET_AND_WAIT, 10, {255, 0, 0,0}},
        {SET_AND_WAIT, 10, {0, 0, 0, 255}},
        {SET_AND_WAIT, 10, {255, 0, 0,0}},
        {SET_AND_WAIT, 10, {0, 0, 0, 255}},
        {SET_AND_WAIT, 10, {255, 0, 0, 0}},
        {SET_AND_WAIT, 10, {0, 0, 0, 255}},
        {FADE_RANDOM, 50, {255, 255, 255, 0}},
        {FADE_RANDOM, 50, {255, 255, 255, 0}},
        {FADE_RANDOM, 50, {255, 255, 255, 0}},
        {FADE_RANDOM, 50, {255, 255, 255, 0}},
        {SET_AND_WAIT, 50, {0, 0, 255, 0}},
        {SET_AND_WAIT, 50, {0, 255, 255 ,0}},
        {SET_AND_WAIT, 50, {255, 255, 0, 0}},
        {SET_AND_WAIT, 50, {0, 255, 0, 0}},
        {FADE_RANDOM, 50, {255, 255, 255, 0}},
        {FADE_RANDOM, 50, {255, 255, 255, 0}},
        {FADE_RANDOM, 50, {255, 255, 255, 0}},
        {FADE_RANDOM, 50, {255, 255, 255, 0}},
        {FADE_RANDOM, 50, {255, 255, 255, 0}}
      };
      
      
      rgb_cmd* programs[] = {
        &program_ALARM[0], &program_RELAX[0], &program_PARTY[0]
      };
      
      const int program_steps[] = {
        sizeof(program_ALARM)/sizeof(rgb_cmd),
        7,
        22
      };
      
      void setup()
      {
        // Fix the PWM timer. Without this the LEDs will flicker.
        TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00);
      
        // Output pins
        pinMode(REDPIN, OUTPUT);
        pinMode(GREENPIN, OUTPUT);
        pinMode(BLUEPIN, OUTPUT);
        pinMode(WHITEPIN, OUTPUT);
        
      }
      
      void presentation()
      {
      	// Send the Sketch Version Information to the Gateway
      	sendSketchInfo(SN, SV);
      	present(CHILD_ID_LIGHT, S_RGBW_LIGHT);
      }
      
      void selftest() {
        on_off_status = 1;
        current[RR] = 255;
        current[GG] = 0;
        current[BB] = 0;
        current[WW] = 0;
        set_hw_status();
        wait(200);
        current[RR] = 0;
        current[GG] = 255;
        set_hw_status();
        wait(200);
        current[GG] = 0;
        current[BB] = 255;
        set_hw_status();
        wait(200);
        current[BB] = 0;
        current[WW] = 255;
        set_hw_status();
        wait(200);
        current[RR] = 0;
        current[GG] = 0;
        current[BB] = 0;
        set_hw_status();
        wait(200);
        on_off_status = 0;
      }
      
      void loop()
      {
        static bool first_message_sent = false;
        if ( first_message_sent == false ) {
          selftest();
          set_hw_status();
          send(rgbwMsg.set(rgbwstring));
          send(lightMsg.set(on_off_status));
          send(dimmerMsg.set(dimmerlevel));
          send(prgspeedMsg.set(prgspeed));
          send(programMsg.set(program_mode));
          first_message_sent = true;
        }
      
        unsigned long now = millis();
        // Maybe we wrapped around? Then reset last_update to 0.
        if (now < last_update) {
          last_update = 0;
        }
        
        if (now - last_update > tick_length) {
          last_update = now;
      
          // If we're fading, finish that before we do anything else
          if (light_mode == LIGHT_FADING) {
            calc_fade();
          } else {
            if (program_mode > PROGRAM_NOP) {
              handle_program();
            }
          }
        }
        
        set_hw_status();
        
      }
      
      void receive(const MyMessage &message)
      {
        int val;
        
      	if (message.type == V_RGBW) {
          for (int i=0; i<=3; i++) {
            temp[i] = hextoint(message.data[i*2]) * 16 + hextoint(message.data[i*2+1]);
          }
          // Save old value
          strcpy(rgbwstring, message.data);
      
          init_fade(prgspeed, temp); 
          send(rgbwMsg.set(rgbwstring));
      
      	} else if (message.type == V_LIGHT || message.type == V_STATUS) {
          val = atoi(message.data);
          if (val == 0 or val == 1) {
            on_off_status = val;
            send(lightMsg.set(on_off_status));
          }
          
        } else if (message.type == V_PERCENTAGE) {
          val = atoi(message.data);
          if (val >= 0 and val <=100) {
            dimmerlevel = val;
            send(dimmerMsg.set(dimmerlevel));
          }
          
        } else if (message.type == V_VAR1 ) {
          val = atoi(message.data);
          if (val >= 0 and val <= 2000) {
            prgspeed = val;
            send(prgspeedMsg.set(val));
          }
      
        } else if (message.type == V_VAR2 ) {
          val = atoi(message.data);
          if (val == PROGRAM_NOP) {
            stop_program();
            send(programMsg.set(val));
          } else {
            init_program(val);
            send(programMsg.set(val));
          }
      
      	} else {
      		return;
      	}
      
      }
      
      void execute_step(rgb_cmd cmd) {
      
        if (cmd.cmd == SET) {
          set_rgb(cmd.rgbw);
        } else if (cmd.cmd == SET_AND_WAIT) {
          set_rgb(cmd.rgbw);
          program_timer = cmd.p;
        } else if (cmd.cmd == SET_RANDOM) {
          set_rgb_random(cmd.rgbw);
        } else if (cmd.cmd == SET_RANDOM_AND_WAIT) {
          set_rgb_random(cmd.rgbw);
          program_timer = cmd.p;
        } else if (cmd.cmd == FADE) {
          init_fade(cmd.p, cmd.rgbw);
        } else if (cmd.cmd == FADE_RANDOM) {
          init_fade_random(cmd.p, cmd.rgbw);
        } else if (cmd.cmd == WAIT) {
          program_timer = cmd.p;
        }
      }
      
      void init_program(int program) {
        program_mode = program;
        program_step = 0;
        program_timer = 0;
        save_state();
        execute_step(programs[program_mode-1][0]);
      }
      
      void handle_program() {
        if (program_timer > 0) {
          program_timer--;
        }
        
        if (program_timer == 0) {
          program_step++;
          if (program_step == program_steps[program_mode-1]) {
            program_step = 0;
          }
          execute_step(programs[program_mode-1][program_step]);
        }
      }
      
      void stop_program() {
        restore_state();
        light_mode = LIGHT_NORMAL;
        program_mode = PROGRAM_NOP;
      }
      
      void save_state() {
        memcpy(save, current, 4 );
      }
      
      void restore_state() {
        memcpy(current, save, 4 );
      }
      
      void set_rgb (byte rgbw[]) {
        light_mode = LIGHT_NORMAL;
        memcpy(current, rgbw, 4);
      }
      
      void set_rgb_random (byte rgbw[]) { 
        light_mode = LIGHT_NORMAL;
        for (int i=0; i <= 3; i++){
          current[i] = random(rgbw[i]);
        }
      }
      
      void init_fade(int t, byte rgbw[]) {
        light_mode = LIGHT_FADING;
        fade_step = t;
        memcpy(target, rgbw, 4);
        for (int i=0; i<=3; i++) {
          delta[i] = (target[i] - current[i]) / float(fade_step);
        }
      }
      
      void init_fade_random(int t, byte rgbw[]) {
        light_mode = LIGHT_FADING;
        fade_step = t;
        for (int i=0; i<=3; i++) {
          target[i] = random(rgbw[i]);
          delta[i] = (target[i] - current[i]) / float(fade_step);
        }
      }
      
      void calc_fade() {
        if (fade_step > 0) {
          fade_step--;
          for (int i=0; i<=3; i++) {
           current[i] = target[i] - delta[i] * fade_step;
          }
        } else {
          light_mode = LIGHT_NORMAL;
        } 
      }
      
      void set_hw_status() {
        analogWrite(REDPIN, on_off_status * (int)(current[RR] * dimmerlevel/100.0));
        analogWrite(GREENPIN, on_off_status * (int)(current[GG] * dimmerlevel/100.0));
        analogWrite(BLUEPIN, on_off_status * (int)(current[BB] * dimmerlevel/100.0));
        analogWrite(WHITEPIN, on_off_status * (int)(current[WW] * dimmerlevel/100.0));
      }
      
      byte hextoint (byte c) {
         if ((c >= '0') && (c <= '9')) return c - '0';
         if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10;
         if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10;
         return 0;
      }
      
      posted in My Project
      maghac
      maghac
    • RE: What did you build today (Pictures) ?

      Built a heat pump monitor based on mysensors on an Nano board and a few LM393 light sensors.

      It's simply reading the status LEDs and tells me if they're on or off, and it means I can correlate e.g the compressor or circulation pumps with the electricity usage read from the power meter.

      Also, which actually was the main driver behind the project, it allows me to send an alarm to my phone in case the alarm LED goes on. This is usually caused by incorrect pressure somewhere in the system and can be fixed by simply restarting the system. When the alarm triggers, it shuts down everything which is a bit annoying since it can take a few hours before I notice it (usually not until I go in the shower and there is no hot water). I now have to figure out how to deal with the fact that the alarm LED is blinking, which causes a stream of "alarm ON, alarm OFF, alarm ON, ... ." etc messages in Telegram 🙂 There should be a way to fix this in Home Assistant I hope.

      An interesting thing was that I was not able to tune the sensors to give me an accurate on/off digital signal. I therefore have to read the analog signal, and in the sketch decide whether it's on or off depending on the value. The values are in the 0..1023 range and the threshold was somewhere around 1000, so I think it was too close to the end of the range for the adjustment potentiometer.

      photo_2020-01-28_22-19-25.jpg
      photo_2020-01-28_22-19-31.jpg
      photo_2020-01-28_22-19-34.jpg
      photo_2020-01-28_22-19-38.jpg
      photo_2020-01-28_22-19-42.jpg

      posted in General Discussion
      maghac
      maghac
    • RE: 💬 Power Meter Pulse Sensor

      @martinhjelmare Yep, I figured I could do that. The absolute value is not so important actually, I'm more interested in the daily/weekly delta, which I hope Grafana can tell me.

      posted in Announcements
      maghac
      maghac
    • RE: RGB LED strip

      @OliverDog, thanks!

      The V_VAR1 message is used to set the speed of the fading (e.g the time between stepping the RGB values towards the value received with the V_RGB message). Not sure why it doesn't work for you, but maybe it's related to the fact that you don't have the real RGB leds?

      You may be interested to know that I have implemented a new version of this sketch. The problem with the old one is that it did the fading in a loop which meant that no new commands were processed during the fade. The new version implements it differently so that messages can be received while the light is fading in a sort of multitasking fashion. This opened up the possibility to implement "programs" that control the LED strip in the background while the device is still receiving messages (e.g during a slow fade to green I can tell it to turn off or to fade to blue instead, without having to wait for the current fade to stop). I have implemented two such programs - one is a sort of an alarm mode (blink white on/off) and the other is a relax program (very slow fade between various pastel colours). To enable the programs, you send a V_VAR2 message with a number: 0: normal (e.g fixed to one colour), 1: alarm and 2: relax.

      Since V_VAR2 is message type 25, this is the corresponding MQTT message to enable the relax program:

      mosquitto_pub -t mysensors-in/2/1/1/0/25 -m 2
      

      Code is below. I intend to update it further (i.e the "party" program is missing! 🙂 ) and then I'll post the new versions here.

      Have fun!

      /**
       * This program is free software; you can redistribute it and/or
       * modify it under the terms of the GNU General Public License
       * version 2 as published by the Free Software Foundation.
       *
       * LED STRIP sketch for Mysensors
       *******************************
       *
       * REVISION HISTORY
       * 1.0 
       *   Based on the example sketch in mysensors
       * 1.1
       *   fadespeed parameter (send as V_VAR1 message)
       *   HomeAssistant compatible (send status to ack)
       * 1.2
       *   OTA support
       * 1.3
       *   Power-on self test
       * 1.4
       *   Bug fix
       * 1.5
       *   Other default values
       * 1.6
       *   Repeater feature
       * 1.7
       *   Multitasking. Alarm, Relax and normal modes.
       */
      
      #define MY_OTA_FIRMWARE_FEATURE
      #define MY_REPEATER_FEATURE
      #define MY_NODE_ID AUTO
      
      #define MY_RADIO_NRF24
      
      #define MY_DEBUG
      
      #include <MySensors.h>
      
      #define CHILD_ID_LIGHT 1
      
      #define SN "LED Strip"
      #define SV "1.7"
      
      MyMessage lightMsg(CHILD_ID_LIGHT, V_LIGHT);
      MyMessage rgbMsg(CHILD_ID_LIGHT, V_RGB);
      MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER);
      
      int current_r = 255;
      int current_g = 255;
      int current_b = 255;
      int target_r = 255;
      int target_g = 255;
      int target_b = 255;
      int save_r;
      int save_g;
      int save_b;
      
      
      float delta_r = 0.0;
      float delta_g = 0.0;
      float delta_b = 0.0;
      
      char rgbstring[] = "ffffff";
      
      int on_off_status = 0;
      int dimmerlevel = 100;
      int fadespeed = 20;
      unsigned long last_update = 0;
      int tick_length = 10;
      int fade_step = 0;
      
      int program_timer;
      int program_cycle;
      
      #define REDPIN 6
      #define GREENPIN 5
      #define BLUEPIN 3
      
      #define LIGHT_NORMAL 0
      #define LIGHT_FADING 1
      
      #define PROGRAM_NORMAL 0
      #define PROGRAM_ALARM 1
      #define PROGRAM_RELAX 2
      
      int light_mode = LIGHT_NORMAL;
      int program_mode = PROGRAM_NORMAL;
      
      #define RELAX_SPEED 50
      #define MAX_CYCLES_RELAX 7
      const int program_param_RELAX[MAX_CYCLES_RELAX][3] = {
        {255, 32, 0},
        {255, 32, 16},
        {255, 16, 32},
        {255, 128, 0},
        {255, 32, 00},
        {255, 32, 32},
        {255, 0, 32}
      };
      
      void setup()
      {
        // Fix the PWM timer. Without this the LEDs will flicker.
        TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00);
      
        // Output pins
        pinMode(REDPIN, OUTPUT);
        pinMode(GREENPIN, OUTPUT);
        pinMode(BLUEPIN, OUTPUT);
        
      }
      
      void presentation()
      {
      	// Send the Sketch Version Information to the Gateway
      	sendSketchInfo(SN, SV);
      	present(CHILD_ID_LIGHT, S_RGB_LIGHT);
      }
      
      void selftest() {
        on_off_status = 1;
        current_r = 255;
        current_g = 0;
        current_b = 0;
        set_hw_status();
        wait(100);
        current_r = 0;
        current_g = 255;
        set_hw_status();
        wait(100);
        current_g = 0;
        current_b = 255;
        set_hw_status();
        wait(100);
        current_r = 255;
        current_g = 255;
        set_hw_status();
        wait(100);
        on_off_status = 0;
      }
      
      
      void loop()
      {
        static bool first_message_sent = false;
        if ( first_message_sent == false ) {
          selftest();
          set_hw_status();
          send_status(1, 1, 1);
          first_message_sent = true;
        }
      
        unsigned long now = millis();
        
        if (now - last_update > tick_length) {
          last_update = now;
      
          if (light_mode == LIGHT_FADING) {
            calc_fade();
          }
      
          if (program_mode > PROGRAM_NORMAL) {
            handle_program();
          }
          
        }
        set_hw_status();
        
      }
      
      void receive(const MyMessage &message)
      {
        int val;
        
      	if (message.type == V_RGB) {
      		Serial.print( "V_RGB: " );
          Serial.println(message.data);
          long number = (long) strtol( message.data, NULL, 16);
      
          // Save old value
          strcpy(rgbstring, message.data);
          
          // Split it up into r, g, b values
          int r = number >> 16;
          int g = number >> 8 & 0xFF;
          int b = number & 0xFF;
      
          init_fade(fadespeed, r, g, b); 
          send_status(0, 0, 1);
      
      	} else if (message.type == V_LIGHT || message.type == V_STATUS) {
          Serial.print( "V_LIGHT: " );
          Serial.println(message.data);
          val = atoi(message.data);
          if (val == 0 or val == 1) {
            on_off_status = val;
            send_status(1, 0, 0);
          }
          
        } else if (message.type == V_DIMMER || message.type == V_PERCENTAGE) {
          Serial.print( "V_DIMMER: " );
          Serial.println(message.data);
          val = atoi(message.data);
          if (val >= 0 and val <=100) {
            dimmerlevel = val;
            send_status(0, 1, 0);
          }
          
        } else if (message.type == V_VAR1 ) {
          Serial.print( "V_VAR1: " );
          Serial.println(message.data);
          val = atoi(message.data);
          if (val >= 0 and val <= 2000) {
            fadespeed = val;
          }
      
        } else if (message.type == V_VAR2 ) {
          Serial.print( "V_VAR2: " );
          Serial.println(message.data);
          val = atoi(message.data);
          if (val == PROGRAM_NORMAL) {
            stop_program();
          } else if (val == PROGRAM_ALARM || val == PROGRAM_RELAX) {
            init_program(val);
          }
      
      	} else {
      		Serial.println( "Invalid command received..." );
      		return;
      	}
      
      }
      
      void set_rgb(int r, int g, int b) {
        analogWrite(REDPIN, r);
        analogWrite(GREENPIN, g);
        analogWrite(BLUEPIN, b);
      }
      
      void init_program(int program) {
        program_mode = program;
        program_cycle = 0;
        save_rgb();
        
        if (program == PROGRAM_ALARM) {
          light_mode = LIGHT_NORMAL;
          current_r = 255;
          current_g = 255;
          current_b = 255;
          program_timer = 50;
        } else if (program == PROGRAM_RELAX) {
          program_timer = 300;
          init_fade(fadespeed,
                    program_param_RELAX[program_cycle][0],
                    program_param_RELAX[program_cycle][1],
                    program_param_RELAX[program_cycle][2]);
        }
      }
      
      void handle_program() {
        program_timer--;
        if (program_mode == PROGRAM_ALARM) {
          if (program_timer == 0) {
            program_timer = 50;
            if (program_cycle == 0) {
              program_cycle = 1;
              current_r = 0;
              current_g = 0;
              current_b = 0;
            } else {
              program_cycle = 0;
              current_r = 255;
              current_g = 255;
              current_b = 255;
            }
          }
        } else if (program_mode == PROGRAM_RELAX) {
          if (light_mode == LIGHT_NORMAL) {
            program_cycle = (program_cycle+1) % MAX_CYCLES_RELAX;
            Serial.print("Next cycle step ");
            Serial.println(program_cycle);
            init_fade(fadespeed * RELAX_SPEED,
                      program_param_RELAX[program_cycle][0],
                      program_param_RELAX[program_cycle][1],
                      program_param_RELAX[program_cycle][2]);
          
          }
          
        }
      }
      
      void stop_program() {
        restore_rgb();
        light_mode = LIGHT_NORMAL;
        program_mode = PROGRAM_NORMAL;
      }
      
      void save_rgb() {
        save_r = current_r;
        save_g = current_g;
        save_b = current_b;
      }
      
      void restore_rgb() {
        current_r = save_r;
        current_g = save_g;
        current_b = save_b;
      }
      void init_fade(int t, int r, int g, int b) {
        Serial.print( "Init fade" );
        light_mode = LIGHT_FADING;
        target_r = r;
        target_g = g;
        target_b = b;
        fade_step = t;
        delta_r = (target_r - current_r) / float(fade_step);
        delta_g = (target_g - current_g) / float(fade_step);
        delta_b = (target_b - current_b) / float(fade_step);
      }
      
      void calc_fade() {
        if (fade_step > 0) {
          fade_step--;
          current_r = target_r - delta_r * fade_step;
          current_g = target_g - delta_g * fade_step;
          current_b = target_b - delta_b * fade_step;
        } else {
          Serial.println( "Normal mode" );
          light_mode = LIGHT_NORMAL;
        } 
      }
      
      void set_hw_status() {
        int r = on_off_status * (int)(current_r * dimmerlevel/100.0);
        int g = on_off_status * (int)(current_g * dimmerlevel/100.0);
        int b = on_off_status * (int)(current_b * dimmerlevel/100.0);
      
        set_rgb(r, g, b);
        
      }
      
      
      void send_status(int send_on_off_status, int send_dimmerlevel, int send_rgbstring) {
        if (send_rgbstring) send(rgbMsg.set(rgbstring));
        if (send_on_off_status) send(lightMsg.set(on_off_status));
        if (send_dimmerlevel) send(dimmerMsg.set(dimmerlevel));
      }
      
      posted in My Project
      maghac
      maghac
    • RE: What did you build today (Pictures) ?

      @mfalkvidd said in What did you build today (Pictures) ?:

      Today I finally got my thumbs out and upgraded my plant monitoring to MySensors 2.x (from 1.x).
      Updated sketch is available on Github: https://github.com/mfalkvidd/arduino-plantmoisture

      Result: I really need to water my plants 😉 But the 2.5 year old batteries are still going strong.
      0_1521737262850_PlantMonitoringDomoticz-2018-03-22.png

      What kind of components is this running on? I am having trouble getting my batteries to run even 2.5 months (or 2.5 weeks for the outside temp sensor...) 🙂

      posted in General Discussion
      maghac
      maghac
    • RE: 💬 MyController.org

      Would it be possible to use this ONLY to manage OTA updates for a network of MySensors nodes using the MQTT protocol? I have a ESP8266 based MQTT gateway but I'm using a different controller.

      posted in Announcements
      maghac
      maghac

    Latest posts made by maghac

    • RE: (Solved) S_Multimeter in HomeAssistant

      @Joost Perhaps you started the node at some point during development without presenting the sensors? If HA has already seen your node before, I think it will not update its children/sensors again even if you restart and have the node send the presentation again. What I do when this happens is to shut down HA, remove the entry from the json file and restart HA again. Then restart the node so it presents itself again.

      posted in Home Assistant
      maghac
      maghac
    • RE: What did you build today (Pictures) ?

      @Nca78 You're probably correct. I first wanted to keep the sensor "dumb" and put all logic in the controller, but it makes sense that the sensor actually returns the true alarm state - which is ON if the LED is blinking.

      posted in General Discussion
      maghac
      maghac
    • RE: What did you build today (Pictures) ?

      Built a heat pump monitor based on mysensors on an Nano board and a few LM393 light sensors.

      It's simply reading the status LEDs and tells me if they're on or off, and it means I can correlate e.g the compressor or circulation pumps with the electricity usage read from the power meter.

      Also, which actually was the main driver behind the project, it allows me to send an alarm to my phone in case the alarm LED goes on. This is usually caused by incorrect pressure somewhere in the system and can be fixed by simply restarting the system. When the alarm triggers, it shuts down everything which is a bit annoying since it can take a few hours before I notice it (usually not until I go in the shower and there is no hot water). I now have to figure out how to deal with the fact that the alarm LED is blinking, which causes a stream of "alarm ON, alarm OFF, alarm ON, ... ." etc messages in Telegram 🙂 There should be a way to fix this in Home Assistant I hope.

      An interesting thing was that I was not able to tune the sensors to give me an accurate on/off digital signal. I therefore have to read the analog signal, and in the sketch decide whether it's on or off depending on the value. The values are in the 0..1023 range and the threshold was somewhere around 1000, so I think it was too close to the end of the range for the adjustment potentiometer.

      photo_2020-01-28_22-19-25.jpg
      photo_2020-01-28_22-19-31.jpg
      photo_2020-01-28_22-19-34.jpg
      photo_2020-01-28_22-19-38.jpg
      photo_2020-01-28_22-19-42.jpg

      posted in General Discussion
      maghac
      maghac
    • RE: RGB LED strip

      Hi,
      yes, W is just another channel and it works the same way as the RGB channels. There is one single on/off and dimmer amount for all 4 channels. In Home Assistant this works as expected - there is one single unit which has a color selector for RGB values and a slider for the W value.

      Not sure why Domoticz shows it as two separate units - perhaps you can check if there is an option to modify this behaviour?

      posted in My Project
      maghac
      maghac
    • RE: [SOLVED] NRF24 can not sleep

      @mfalkvidd How do you measure such low currents? I have the problems with some nodes that are consuming way too much power and I'd like to check them.

      posted in Development
      maghac
      maghac
    • RE: What did you build today (Pictures) ?

      @mfalkvidd said in What did you build today (Pictures) ?:

      Today I finally got my thumbs out and upgraded my plant monitoring to MySensors 2.x (from 1.x).
      Updated sketch is available on Github: https://github.com/mfalkvidd/arduino-plantmoisture

      Result: I really need to water my plants 😉 But the 2.5 year old batteries are still going strong.
      0_1521737262850_PlantMonitoringDomoticz-2018-03-22.png

      What kind of components is this running on? I am having trouble getting my batteries to run even 2.5 months (or 2.5 weeks for the outside temp sensor...) 🙂

      posted in General Discussion
      maghac
      maghac
    • RE: RGB LED strip

      @dmonty said in RGB LED strip:

      Just finished a similar project using WS2812B.

      • MySensors/Domoticz support.
      • Infrared Remote support (common 44 key color picker)
      • Color change & fade animations ++.

      https://github.com/dmonty2/ir_remote_leds/tree/mysensors

      Cool. I've played with WS2812B and FastLed in another project. But I'm not sure if they are good enough for general illumination though?

      posted in My Project
      maghac
      maghac
    • RE: RGB LED strip

      @bgunnarb said in RGB LED strip:

      @maghac I have implemented your 1.8 and I am impressed with the good structure and the performance of your code! Kudos!

      Thanks! Let me know if you have any problems with it - I am still facing some issues actually. After some time (a couple of days or so), the LED strip does not respond to on/off commands any longer. I've implemented a debug feature to try to diagnose the cause of it (I send the node a V_TEXT message and it responds with a series of V_TEXT messages containing the values of variables).

      posted in My Project
      maghac
      maghac
    • RE: MySensors 2.2.0 released

      Hi,
      I've noticed that since the upgrade to 2.2.0 my nodes are now sending some new internal messages every now and then. I'm using a MQTT gateway and sometimes I see these messages coming through:

      mysensors-out/1/255/3/0/33 600000
      mysensors-out/1/255/3/0/32 500

      What are internal messages types 32 and 33? Can't find them in the list on https://www.mysensors.org/download/serial_api_20#internal

      posted in Announcements
      maghac
      maghac
    • RE: 💬 Connecting the Radio

      @gohan But then I would need additional hardware to use DualOptiBoot?

      Anyone have any quick instructions on how to build a new custom version of MySensorsBootLoader using MY_RF24_CE_PIN = 8 😉

      I have access to ArduinoIDE on Windows or a Ubuntu 16.04 box.

      posted in Announcements
      maghac
      maghac