-->
Page 1 of 1

Wifi-controlled white and RGB LED lamp w/dimmer

PostPosted: Fri Apr 24, 2015 3:05 pm
by ArnieO
I am about to replace our bedroom ceiling lamp with this thing, hacked into a generously large IKEA plastic lamp that has been unused and one a shelve for some years:
Image
As I wanted good brightness warm white light plus an option of "ambiance lighting", I decided to install:
For the white light:
For the color lighting I used 4 pcs 5050 RGB LED stripe.

I have found the tape glue on the back side of these LED stripes to not be reliable over time, so I spent a messy half-hour removing the adhesive using isopropanol. It was not easy, so if anyone has a better way to do it - please let me know! After soldering wires to them, I hotglued the LED stripes in place as shown.

I wanted the four channels (white, red, green, blue) controlled individually, with dimmer, driven from an ESP8266. The white circuit draws around 1,5 amp at 12V, so the best suited FET I found in my drawers to switch that was an IRF540 (N-channel). This is not a logic-level FET, so cannot be driven by the ESP directly, so 2N2222's are used to drive the FETs.
I selected an ESP-03, which has enough GPIO pins. I used GPIO2 on one of the channels. GPIO0 and GPIO2 must either be floating or pulled high at power-on for the ESP to start up correctly. This is why the 2N2222 connected to GPIO2 has an extra pullup resistor.

My electronics board is powered by a 230VAC/12VDC adapter, and a small step-down module provides 3,3VDC for the ESP.

The firmware on the ESP is the integer version of NodeMCU.
https://github.com/nodemcu/nodemcu-firm ... v_20150406

The lamp is controlled via an EasyIoT server running on my Raspberry Pi 2: http://iot-playground.com/
The EasyIoT server generates a web page that can be accessed from any device inside our home wifi network:
Image

The Lua code running on the ESP is:
Code: Select all------------------------------------------------------------------------------
-- Lua driver for RGBW dimmer node
-- Written to work as an EasyIoT Virutal Node
-- http://iot-playground.com/forum/general/102-nodemcu-dimmer-switch-temp-sensor-without-arduino
-- https://github.com/DennisSc/easyIoT-nodeMCU
-- Based on QuinLED_ESP8266_V0.4       
-- http://blog.quindorian.org/2014/12/esp8266-wifi-led-dimmer-part-1-of-x.html
--
-- Signals are inverted
--
-- ArnieO, 16 april 2015
------------------------------------------------------------------------------

-- PARAMETERS
CHANR=6 -- GPIO12
CHANG=7 --GPIO13
CHANB=5 --GPIO14
CHANW=4 --GPIO2
--SSID & PW
SSID = "YourSSID"
PW = "YourNetworkPassword"
IPADR = "192.168.0.172"
IPROUTER = "192.168.0.1"

-- Start with all lights off
pwm.setup(CHANR, 500, 1023)
pwm.setup(CHANG, 500, 1023)
pwm.setup(CHANB, 500, 1023)
pwm.setup(CHANW, 500, 0)
pwm.start(CHANR)
pwm.start(CHANG)
pwm.start(CHANB)
pwm.start(CHANW)

CHAN=0

-- Inverted values: 1023 = OFF
LEDR_current=1023
LEDG_current=1023
LEDB_current=1023
LEDW_current=0
LED_current=1023

Fadetime=1000

Stepcounter=0
PosStepcounter=0
DimTimer=0

--StepcounterG=0
--PosStepcounterG=0
--DimTimerG=0

--StepcounterB=0
--PosStepcounterB=0
--DimTimerB=0

wifi.setmode(wifi.STATION)
wifi.sta.setip({ip=IPADR,netmask="255.255.255.0",gateway=IPROUTER})
wifi.sta.config(SSID,PW)

srv=net.createServer(net.TCP)
srv:listen(43333,function(conn)
     conn:on("receive",function(conn,payload)

          print("\nInput: "..payload)

          -- Inverting the received value: 1023 -> 0, 0 -> 1023
          LED_target=tonumber(string.sub(payload, 13) )
          LED_target = 1023 - LED_target
         
          print("Led_target= "..LED_target)
 
          if string.find(payload,"LEDR") then
               dimmerchannel = "R"
               LED_current = LEDR_current
               LEDR_target = LED_target
               LEDR_current = LEDR_target
               CHAN = CHANR
          elseif string.find(payload,"LEDG") then
               dimmerchannel = "G"
               LED_current = LEDG_current
               LEDG_target = LED_target
               LEDG_current = LEDG_target
               CHAN = CHANG
          elseif string.find(payload,"LEDB") then
               dimmerchannel = "B"
               LED_current = LEDB_current
               LEDB_target = LED_target
               LEDB_current = LEDB_target
               CHAN = CHANB
          elseif string.find(payload,"LEDW") then
               dimmerchannel = "W"
               LED_current = LEDW_current
               LEDW_target = LED_target
               LEDW_current = LEDW_target
               CHAN = CHANW
          end
             
         
          print("Received LED"..dimmerchannel.." Target Value: "..LED_target)

          Stepcounter=(LED_target)-(LED_current)
     
          if (Stepcounter) < 0 then
               PosStepcounter= - (Stepcounter)
          else PosStepcounter=(Stepcounter)
          end
     
         -- if (PosStepcounter) == 0 then
         --      PosStepcounter=1
         -- end
         if (PosStepcounter) == 0 then
            PosStepcounter=(PosStepcounter)+1
         else PosStepcounter=(PosStepcounter)
         end
         
          DimTimer=(Fadetime)/(PosStepcounter)

          if (DimTimer) == 0 then
               DimTimer=1 
          end

          print ("Dimmer channel "..dimmerchannel..":")
          print ("Fadetime: "..Fadetime)
          print ("Stepcounter: "..Stepcounter)
          print ("PosStepcounter: "..PosStepcounter)
          print ("DimTimer: "..DimTimer)
          print ("LED_current: "..LED_current)
          print ("LED_target: "..LED_target)
   
          tmr.alarm(0, (DimTimer), 1, function()
               if LED_current < LED_target then
                    LED_current = (LED_current + 1)
                    pwm.setduty(CHAN, LED_current)
               elseif LED_current > LED_target then
                    LED_current = (LED_current - 1)
                    pwm.setduty(CHAN, LED_current)
               elseif LED_current == LED_target then
                    tmr.stop(0)
               end
          end)         
     end)
end)

print ("EasyIoT dimmer/switch sensor for nodeMCU")
print ("Based on QuinLED_ESP8266_V0.4_") 


The starting point for this code was shamelessly stolen from the forum over at http://iot-playground.com/ - then modified some.

All PWM values are inverted, so that OFF is 1023 and ON is 0. The reason for this is that the 2N2222 drivers will switch the FETS on when the GPIOs are low and vice versa. The fade time is one second.

At power-up, the Lua code initializes so that the white light is fully on, the RGB LEDs off. In this way, the wall switch in our bedroom will work almost as with a normal lamp - except that once power is on, the lamp can be controlled from the closest smartphone or tablet.

Image
The white LEDs are connected to J2, the RGBs to J3/J4.

I soldered this on a 5x7 cm perfboard hotglued to the lamp base. The ESP-03 is placed in a socket so that it can be programmed separately then plugged in.

Image

The automation on the EasyIoT server is four very similar programs, this is for the white channel:
Code: Select all// dimmer node N4S0 WHITE
const String ESP8266_IP_ADDRESS = "192.168.0.172";
const String NODE_ADDRESS = "N4S0";
const String NODE_COLOR = "W";   // Set dimmer color channel here: R, G or B - or W
int myVal;
 
/*
This code is running one time when program is enabled
*/
public void Setup()
{
   EventHelper.ModuleChangedHandler((o, m, p) =>
   {
      if (m.Domain == "Virtual" && m.Address == NODE_ADDRESS)
      {
           Console.WriteLine("\r\n"+ m.Domain +" "+ m.Address +" in program id "+ Program.ProgramId.ToString() +" property "+ p.Property +" value "+ p.Value);
             Console.WriteLine("Program was triggered by change of "+ p.Property +" for node id "+ m.Address);
             switch (p.Property)
            {
              case "Sensor.DimmerLevel":
                 myVal = ConvertRange(0, 100, 0, 1023, Convert.ToInt32(p.Value));
            Console.WriteLine("Mapped "+ p.Property  +" value of "+ p.Value +" to pwm value "+ myVal + "\r\n");
            sendToServer("LED" + NODE_COLOR + "_target=" + myVal.ToString());
                break;
              case "Sensor.DigitalValue":
                if (myVal == 1)
                  myVal = 1023;
                Console.WriteLine("triggering \"Sensor.DimmerLevel\" event...\r\n");
                 //sendToServer("LED" + NODE_COLOR + "_target="+myVal);
                 ModuleHelper.SetProperty(m.Domain, m.Address, "Sensor.DimmerLevel", (Convert.ToInt32(p.Value)*100).ToString());
               EventHelper.SetEvent(m.Domain, m.Address, "Sensor.DimmerLevel");             
                 break;
              default:
                 break;
            } //end switch
        }//end if
   return true;
   });//end EventHelper
}

/*
This code is running periodicaly when program is enabled.
Cron job determine running period.
*/
public void Run()
{}

private void sendToServer(String message)
{
   try
   {
      Console.WriteLine("TCP client command:" + message + "\r\n");
      Int32 port = 43333;
      System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient( ESP8266_IP_ADDRESS, port);
      Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
      System.Net.Sockets.NetworkStream stream = client.GetStream();
      stream.Write(data, 0, data.Length);
      // Close everything.
      stream.Close();
      client.Close();
   }
   catch(Exception e)
   {
      Console.WriteLine(e.StackTrace + "\r\n");
   }
}

private static int ConvertRange(
    int originalStart, int originalEnd, // original range
    int newStart, int newEnd, // desired range
    int value) // value to convert
{
    double scale = (double)(newEnd - newStart) / (originalEnd - originalStart);
    return (int)(newStart + ((value - originalStart) * scale));
}


Photos with low light intensity:
Image
Image

With the lamp cover on (unfortunately some shadow from the power supply):
Image

Re: Wifi-controlled white and RGB LED lamp w/dimmer

PostPosted: Sun Oct 11, 2015 8:31 pm
by nathes2016
Very good learning

Re: Wifi-controlled white and RGB LED lamp w/dimmer

PostPosted: Thu Jan 26, 2017 12:42 pm
by kkman20xx
Thank you for sharing. I was trying to drive a IRF540 directly from a ESP-01 with a 1k resistor and the ESP-01 keep failing to start and now I know why. I was trying to choose between a TIP120 or IRF540 (which I have a few of both).