Introduction: DIY Portable Video Light

The key for good Photos and Videos is lighting. However lighting is generally not very expensive, more complex, mobile solutions with long battery runtime can get expensive quickly.

This guide will show you how to build a cheap universal LED light that is portable and versatile and the best thing, you can make it so it fits your needs best. The completed build has the following features:

  • Powered by rechargeable lithium battery (4x18650)
  • High quality light output (Ra 80+)
  • High brightness (around 2000lm)
  • Adjustable color temperature (4000K - 6000K)
  • Micro controller inside (allows for different programs)

How it works

Changing the color temperature works by mixing the light of two different LED strips with different light colors. The range depends on the LED strips you use. Color temperatures under 3300K are generally considered as warm white, between 3300 and 5000 it's called neutral and above 5000 it's called cold white. Daylight is situated around 6000K and a tungsten light bulb around 4000K. The basic idea is that you can enter a color value into your light and by mixing the two lights you can fit your lighting to every situation. Because the light is approximately settable to a certain color you cold even use the same value to set the white balance of your camera. Or you could set other lights accordingly.

Step 1: Get the Parts!

Notice: I just provide purchase links to show what i personally used. There may be better or cheaper options.

The LEDs

In many ways good parts are the key for this build. You need good quality LED strips in order to make your build suitable for Video and Photography work. Don't even consider using the cheapest LED strips available its very likely that your Photos and Videos will not only end up with a green or magenta tint but also skin tones will render horrible. Also high quality LEDs tend to be much more effective, wich means that you get more light for the energy you are using up. Therefore getting more out of the batteries you are carrying around. Especially for this portable build this is nice to have.

When buying the LEDs you should search for terms like "CRI", "Ra 80+", "Ra 90+". Sometimes such LEDs can be hard to come by by a reasonable price. Also consider buying the LED strips directly from china to save some money. You really should not spend more then 30€ per 5 meter roll.Try looking at places like eBay, amazon or aliexpress. Reasonable prized ones can be found here.

The case

The case should of course be big enough to house all the components and small enough so it can be easily carried around. Another important thing to consider when it comes to enclosure is heat! You want to choose a case that is able to dissipate all the heat your LEDs are generating. So a metal enclosure would be great because it saves us an extra heat sink. The area on one of the sides of your compartment should be big enough to house all of the LEDs you want (obviously). I used this one, if you are not from Germany try to find something similar on Ebay.

The batteries

When buying 18650 Lithium-Ion-Batteries it is important to look for good building quality. Don't make the mistake to buy the cheapest options on eBay. Those Chinese no name batteries won't make you happy because most of them won't hardly come over 900mAh also they are claiming absurd capacities like 9Ah or similar - It's just a lie. You should get some decent branded 18650s instead. Just look for common manufacturers like Sony, Panasonic, Samsung or similar. Those batteries will at least have a data sheet and hold their specifications. I recommend these batteries.

The BMS

A Battery Management System can be extremely helpful to make your lithium-powered project safe. They are very cheap and can be ordered for different configurations (1 cell, 2cells etc.). A 4 cell one can be found here

The display

The display is very cheap and only costs about 4€. It's a dot matrix OLED one with integrated logic so that it can be driven by I2C. Its size is roughly 1" diagonally. Just search for the keywords "1" display", "oled", "i2c" etc. An example can be found here.

The rotary encoder

The rotary encoder really makes the feel of the user interface. Using a rotary encoder with an integrated click button feels very intuitive and looks professional. Also its just one hole in the enclosure. A cheap one can be found here.

The DC/DC converter

You will need a step down DC/DC converter that can handle 3 Amps (at least 1.5). We will get 16.8 Volts peak from the batteries. And need to drop it down to 12V for the LEDs. Also you need a second voltage regulator for 5V. A 12V one can be found here. An example for a 5V can be found here. Maybe you can also make it into a power bank if you add a USB plug with decent current capabilities.

Step 2: The Electronics

Mainboard

The mainboard is kept very simple. An ATmega328 as its commonly used in Arduino UNOs is used for the heart of the project. Two BUZ11 mosfets are controlling the Lights via PWM. (It's fast PWM so you won't see it in video.)

The schematic

  • VREG: The 5V voltage regulator. Pin 1 is the input pin 2 GND and pin 3 5V output.
  • ICSP: The In-Circuit-System-Programmer header. It's used to program the atmega328 with an external programmer. You could use your Arduino as a programmer by using the ArduinoISP sketch. However this caused problems in my case. I decided to build a usbtiny programmer using an attiny85. You could also just use your Arduino UNO as a programmer. Just remember that you don't have a crystal, so use the 8Mhz configuration.
  • TMP1, TMP2, TMP3: Place for 3 NTC 10k Thermistors for temperature monitoring.
  • PAD7, PAD2: Voltage sense. Hook up PAD7 to the negative terminal of your battery pack and PAD2 to the positive. This will meassure the battery voltage. But because we are using PWM the readings fluctuate a lot. So it's not very accurate.
  • LEDS: Hook up the plus pole to 1 and 4 and the minus poles to 2 and 3. If the warm/cold logic is flipped you can just reverse the plug.
  • JP3: 1: 5V; 2: GND; 3: Button1; 4: DT; 5: CLK; 6: SDA; 7: SCL.
  • The button to change modes is missing in the schematic because it was added later on!!! Dont forget to add it. It has to be added on Arduino pin 7 wich corresponds to the 13th hardware pin. And the other terminal of the button needs to go to ground. The Arduino sketch uses an internal pullup resistor, so you won't need a pull down. Depending on the button you are using, consider using a small capacitor in parrallel to debounce the signal.

Battery management

There are cheap finished battery protection circuits on eBay and on aliexpress. You can get them for 3 or 4 cells. Be aware that its important wich version you buy, because also they might look the same and have the same circuit board some resistors and capacitors are rearranged for each configuration. Once you have such a BMS board you are pretty much safe. Just hook all the wires up to the battery including the balancing leads. Now the BMS will care about short circuit protection, over discharge, over charge, charging rate etc. You will get a battery pack with two leads coming out of it being the in- and outputs of the BMS at the same time. In order to charge it, just apply something under 25V and it will safely charge the batteries. To discharge just hook your source up to it. It's very easy and safe.

However if you care about extra security you can get a cheap NTC Thermistor (about 0,2€) and let your micro controller check the temperature. If the batteries are overheating you are able to shut down the system, just in case.

Voltage regulation

For voltage regulation, just get a drop down DC-DC converter off eBay that can handle 3A, so you have enough headroom and it won't run hot. Set it to 12V. If your case is running very hot every time, you should consider dropping the Voltage to maybe 11,5V or something.

For the 5V logic you can either use a small DC-DC converter as well or just use the normal power regulator, but keep in mind that you are throwing away energy with a normal regulator, the more current you are drawing the more wasteful it gets.

The LEDs

Use the self adhesive surface of the LED strips to stick them to the front of the device. Drill a hole to fade the cables thru and seal it with epoxy or hot glue.

The mainboard itself

For the mainboard i provide you with a pdf-schematic and eagle files to etch your own circuit board. Eagle is a free software and can be downloaded here. But its also very possible to just use a breadboard.

Putting everything together

If you have chosen a small enclosure to begin with this will be the hardest part. Generally speaking, you want a tight fit so nothing is loose or flies around in the case. Also it's a good idea to insulate sensitive parts against the case (if you are using a metal one). Just secure everything with a combination of hot glue, screws and tape.

Step 3: The Code

Configuring Arduino IDE

You can use the atmega328 in an 16Mhz or 8Mhz configuration. Read here how to set the micro controller to 8Mhz without using a crystal.

What the code does:

Normal mode

  • Adjust light color from 4000K - 6000K
  • Adjust brightness from 0% - 100% (not really full power)

In this mode you won't be able to archive full brightness because 4000K will be LED strip 1 turned on full and 6000K will be LED strip 2 turned on full. The middle will be 50/50. So of possible "200%" you are just getting 100%.

Insane mode

  • Adjust brightness from 0% - 100% (really full power)
  • Adjust light color but not with constant brightness from 4000K - 6000K

This mode is specially made to get the full brightness out of the lamp.

Portion mode (w.i.p.)

for photography work in long exposures. A fixed light amount will be settable and a time in wich the light will dispense. According to this a special brightness will result and the Light will turn off after the desired amount of light is emitted. Also the display will turn off so it won't be visible on camera.

Halogen mode

Just one brightness control. When the light is darker it will be warmer, when it gets bright the light will get colder. Like a real halogen bulb.

Things that may be added in the future:

  • Flicker mode, the lamp will flicker like a broken fluorescent light when its turned on. Maybe a little bit of flickering during continuous light output to emulate one broken light in an array.
  • Torch mode, the lamp will give its best to emulate the light of a torch
  • Strobe mode, with settable on and off time (kind of pointless)
  • Morse mode, the light will just light up when you press the button.

The Arduino Code:

get the latest release or checkout the code and contribute at github.

Stable version but not the latest:

you need to replace the brackets in the #include statement with < and >.

For this code to run you need the following libraries installed:

  • U8glib by oliver
  • PinChangeInterrupt by NicoHood
  • Encoder by Paul Stoffregen
  • Wire (built-in)
//Video Light 1.2<br>//Code by idexe
#include (U8glib.h)
#include (PinChangeInterrupt)
#include (avr/sleep.h)
#include (Wire.h)
#include (Encoder.h)
//Input and Output
#define BUTTON1 8
#define BUTTON_ON 7
#define DT 2
#define CLK 3
#define COLD 9
#define WARM 10
#define OLED_RESET 4
//U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);// for u8g2lib
class Button
{
  public:
    Button(uint8_t pin);
    void begin(bool pull);
    bool pressed();
    bool hold(int timer);
    bool status();
  private:
    bool _oldvalue;
    uint8_t _pin;
    unsigned long _time;
};
class Light
{
  public:
    Light(int pinWarm, int pinCold);
    void begin();
    void brightness(int Int);
    void color(int color);
    void insane(int Int);
  private:
    int _warm;
    int _cold;
    int _int;
    int _color;
    int _superInt;
};
class Screen
{
  public:
    Screen();
    void reset();
    void standby();
    void setBigText(String BigText, bool def);
    void setBattery(int Bat, bool def);
    void setBottom(String Bottom, bool def);
    void setCaption(String Caption, bool def);
    void update();
    void renderChanges();
  private:
    bool _valueChange;
    String _BigText;
    bool _showBigText;
    int _Bat;
    bool _showBat;
    String _Bottom;
    bool _showBottom;
    String _Caption;
    bool _showCaption;
};
Encoder knob(DT, CLK);
class RotEnc
{
  public:
    RotEnc();
    bool check(int lbound, int rbound);
    int getPos();
    void setPos(int lbound, int rbound, int pos);
  private:
    int _pos;
};
class Thermistor
{
  public:
    Thermistor(int analogPin);
    double read(int interval);
  private:
    int _analogPin;
    unsigned long _Time;
    double _Temp;
};
class Voltage
{
  public:
    Voltage(int analogPin);
    double read(int interval);
  private:
    int _analogPin;
    unsigned long _Time;
    double _Volt;
};
RotEnc rotenc;
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST);
Screen screen;
Button button1(BUTTON1);
Button buttonOn(BUTTON_ON);
Light light(WARM, COLD);
Thermistor therm1(0);
Thermistor therm2(1);
//Thermistor therm3(2);
Voltage volt1(3);
void setup() {
  // put your setup code here, to run once:
  TCCR1B = (TCCR1B & 0b11111000) | 0x01;
  light.begin();
  Serial.begin(9600);
  button1.begin(true);
  buttonOn.begin(true);
}
enum prog_state {STANDBY, ON};
prog_state Prog = ON;
enum state {TMP, INT, SUPER_INT};
state State = TMP;
bool superint = false;
bool stateChange = true;
bool progChange = false;
long Tmp = 5000;
long Int = 50;
long Super_Int = 50;
void loop() {
  switch (Prog) {
    case ON: {
        switch (State) {
          case TMP: {//Farbtemperatur einstellen
              if (stateChange) {//Beim ersten ausführen
                screen.setBigText(String(Tmp) + "K", true);
                screen.setCaption("Temperatur", true);
                screen.update();
                rotenc.setPos(-10, 10, (Tmp - 5000) / 100);
                stateChange = false;
              }
              if (rotenc.check(-10, 10)) { //Wenn jemand dreht
                Tmp = rotenc.getPos() * 100 + 5000;
                screen.setBigText(String(Tmp) + "K", true);
                light.color((Tmp - 4000) / 100 * 255 / 20);
              }
              if (button1.pressed()) {//Wenn jemand drückt
                if (superint) {
                  State = SUPER_INT;
                } else {
                  State = INT;
                }
                stateChange = true;
              }
              break;
            }
          case INT: {//Helligkeit einstellen
              if (stateChange) {//Beim ersten ausführen
                screen.setBigText(String(Int) + "%", true);
                screen.setCaption("Helligkeit", true);
                screen.update();
                rotenc.setPos(-10, 10, (Int - 50) / 5);
                stateChange = false;
              }
              if (rotenc.check(-10, 10)) { //Wenn jemand dreht
                Int = rotenc.getPos() * 5 + 50;
                screen.setBigText(String(Int) + "%", true);
                light.brightness(Int / 5 * 255 / 20);
              }
              if (button1.pressed()) {//Wenn jemand drückt
                State = TMP;
                stateChange = true;
              }
              if (button1.hold(1000)) {
                State = SUPER_INT;
                superint = true;
                stateChange = true;
              }
              break;
            }
          case SUPER_INT: {
              if (stateChange) {//Beim ersten ausführen
                screen.setBigText(String(Super_Int) + "%", true);
                screen.setCaption("Insane", true);
                screen.update();
                rotenc.setPos(-10, 10, (Super_Int - 50) / 5);
                stateChange = false;
              }
              if (rotenc.check(-10, 10)) { //Wenn jemand dreht
                Super_Int = rotenc.getPos() * 5 + 50;
                screen.setBigText(String(Super_Int) + "%", true);
                light.insane(Super_Int / 5 * 255 / 20);
              }
              if (button1.pressed()) {//Wenn jemand drückt
                State = TMP;
                stateChange = true;
              }
              if (button1.hold(1000)) {
                State = INT;
                superint = false;
                stateChange = true;
              }
              break;
            }
        }
        //Allways running Code, like screen rendering, temperature and battery monitoring.
        //2 Temp sensor configuration
        char voltstr[5];
        dtostrf(volt1.read(1000) * 16.8 / 810,4,1,voltstr);
        screen.setBottom("LED:" + String(int(therm1.read(1000))) + (char)176 + "C BAT:" + String(int(therm2.read(1000))) + (char)176 + "C " + String(voltstr) + "V", true);
        //3 Temp sensor configuration
        //screen.setBottom("LED:" + String(int(therm1.read(1000))) + (char)176 + "C BAT:" + String(int(therm2.read(1000))) + (char)176 + "C " + String(int(therm3.read(1000))) + (char)176 + "C", true);
        screen.renderChanges();
        if (buttonOn.pressed() && millis() > 1000) {
          //Prog = STANDBY;
          //progChange = true;
          if (superint) {
            superint = false;
            State = INT;
          } else {
            superint = true;
            State = SUPER_INT;
          }
          stateChange = true;
        }
        /*
        if (buttonOn.hold(1000)) {
          Prog = STANDBY;
          progChange = true;
        }
        */
        break;
      }
    case STANDBY: {
        if (millis() <= 1500) {
          Prog = ON;
          stateChange = true;
          break;
        }
        if (progChange) {
          screen.standby();
          screen.renderChanges();
          progChange = false;
        } else {
          if (buttonOn.hold(2000)) {
            Prog = ON;
            stateChange = true;
          }
          //delay(1000);
          //sleepNow();
        }
      }
  }
}
//Button-methods
Button::Button(uint8_t pin) {
  _pin = pin;
  _oldvalue = true;
}
void Button::begin(bool pull) {
  if (pull) {
    pinMode(_pin, INPUT_PULLUP);
  } else {
    pinMode(_pin, INPUT);
  }
}
bool Button::pressed() {
  bool value = digitalRead(_pin);
  if (_oldvalue != value && value == false) {
    _oldvalue = value;
    return true;
  } else {
    _oldvalue = value;
    return false;
  }
}
bool Button::status() {
  return !digitalRead(_pin);
}
bool Button::hold(int timer) {
  if (pressed()) {
    _time = millis();
  }
  if (status()) {
    if (millis() - _time >= timer && millis() - _time <= timer + 100) {
      return true;
    }
  }
  return false;
}
//Light-methods
Light::Light(int pinCold, int pinWarm) {
  _cold = pinCold;
  _warm = pinWarm;
  _int = 128;
  _color = 128;
}
void Light::begin() {
  pinMode(_cold, OUTPUT);
  pinMode(_warm, OUTPUT);
  analogWrite(_warm, _int * _color / 255);
  analogWrite(_cold, _int * (255 - _color) / 255);
}
void Light::color(int color) {
  //Color mix between 0 (cold) and 255 (warm)
  _color = color;
  analogWrite(_warm, _int * _color / 255);
  analogWrite(_cold, _int * (255 - _color) / 255);
}
void Light::brightness(int Int) {
  //Brightness between 0 (dark) and 255 (bright)
  _int = Int;
  analogWrite(_warm, _int * _color / 255);
  analogWrite(_cold, _int * (255 - _color) / 255);
}
void Light::insane(int Int) {
  //Brightness between 0 (dark) and 510 (very bright)
  _superInt = Int;
  int warm = 2* _superInt * _color / 255;
  if (warm > 255) {
    warm = 255;
  }
  int cold = 2* _superInt * (255 - _color) / 255;
  if (cold > 255) {
    cold = 255;
  }
  analogWrite(_warm, warm);
  analogWrite(_cold, cold);
  
}
//Screen-methods
Screen::Screen() {
#ifndef u8glib_h
#define u8glib_h
#include 
#endif
  //U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);// for u8g2lib
  //U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST);
  _valueChange = true;
  _showBigText = false;
  _showBat = false;
  _showBottom = false;
  _showCaption = false;
}
void Screen::reset() {
  _valueChange = false;
}
void Screen::standby() {
  _valueChange = true;
  _showBigText = false;
  _showBat = false;
  _showBottom = false;
  _showCaption = false;
}
void Screen::setBigText(String BigText, bool def) {
  _showBigText = def;
  if (_BigText != BigText) {
    _BigText = BigText;
    _valueChange = true;
  }
}
void Screen::setBattery(int Bat, bool def) {
  _showBat = def;
  if (_Bat != Bat) {
    _Bat = Bat;
    _valueChange = true;
  }
}
void Screen::setBottom(String Bottom, bool def) {
  _showBottom = def;
  if (_Bottom != Bottom) {
    _Bottom = Bottom;
    _valueChange = true;
  }
}
void Screen::setCaption(String Caption, bool def) {
  _showCaption = def;
  if (_Caption != Caption) {
    _Caption = Caption;
    _valueChange = true;
  }
}
void Screen::update() {
  _valueChange = true;
}
void Screen::renderChanges() {
  if (_valueChange == true) {
    u8g.firstPage();
    do {
      //BigText
      if (_showBigText) {
        u8g.setFont(u8g_font_helvB24r);
        u8g.setFontPosCenter();
        char BigText[_BigText.length() + 1];
        _BigText.toCharArray(BigText, _BigText.length() + 1);
        u8g.setPrintPos((128 - u8g.getStrWidth(BigText)) / 2, 35);
        u8g.print(_BigText);
      }
      //Battery
      //Bottom
      if (_showBottom) {
        u8g.setFont(u8g_font_helvB08);
        u8g.setFontPosBaseline();
        u8g.setPrintPos(0, 64);
        u8g.print(_Bottom);
      }
      //Caption
      if (_showCaption) {
        u8g.setFont(u8g_font_helvB08);
        u8g.setFontPosTop();
        char Caption[_Caption.length() + 1];
        _Caption.toCharArray(Caption, _Caption.length() + 1);
        u8g.setPrintPos((128 - u8g.getStrWidth(Caption)) / 2, 0);
        u8g.print(_Caption);
      }
    } while ( u8g.nextPage() );
    reset();
  }
}
//RotEnc-Methods
RotEnc::RotEnc() {
  _pos = -999;
}
bool RotEnc::check(int lbound, int rbound) {
  int pos = knob.read() / 4;
  if (pos != _pos) {
    if (pos < lbound) {
      pos = lbound;
      knob.write(pos * 4);
    }
    if (pos > rbound) {
      pos = rbound;
      knob.write(pos * 4);
    }
    if (pos != _pos) {
      _pos = pos;
      return true;
    } else {
      return false;
    }
  }
}
int RotEnc::getPos() {
  return _pos;
}
void RotEnc::setPos(int lbound, int rbound, int pos) {
  if (pos < lbound) {
    pos = lbound;
  }
  if (pos > rbound) {
    pos = rbound;
  }
  _pos = pos;
  knob.write(_pos * 4);
}
//Thermistor-Methods
Thermistor::Thermistor(int analogPin) {
  _analogPin = analogPin;
  _Time = 0;
}
double Thermistor::read(int interval) {
  unsigned long Time = millis();
  if (_Time + interval < Time) {
    _Temp = analogRead(_analogPin);
    _Temp = log(10000.0 * ((1024.0 / _Temp - 1)));
    _Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * _Temp * _Temp )) * _Temp );
    _Temp = _Temp - 273.15;            // Convert Kelvin to Celcius
    _Time = Time;
    return _Temp;
  }
  return _Temp;
}
//Voltage-Methods
Voltage::Voltage(int analogPin) {
  _analogPin = analogPin;
  _Time = 0;
}
double Voltage::read(int interval) {
  unsigned long Time = millis();
  if (_Time + interval < Time) {
    _Volt = analogRead(_analogPin);
    _Time = Time;
    return _Volt;
  }
  return _Volt;
}
void sleepNow() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  //attachInterrupt(0,wakeUpNow,LOW);
  attachPinChangeInterrupt(digitalPinToPCINT(BUTTON_ON), wakeUpNow, FALLING);
  sleep_mode();
  sleep_disable();
  //detachInterrupt(0);
  detachPinChangeInterrupt(digitalPinToPCINT(BUTTON_ON));
}
void wakeUpNow() {
<pre>}

Step 4: Finished!

Thats it. Now you now everything to build your own portable video light with endless possibilities. It's very bright with its 2000lm, energy efficient, intelligent, customizable and relatively cheap. You can order all of the parts for under 100€ and you will have plenty of LEDs left if you order 5m rolls of each color.

Sample video and pictures are coming soon.

Comments

author
wildatheart123 (author)2016-10-24

Does anyone have the hex-file for the atmega328p? I dont have all the arduino software that's needed..

author
iDexe (author)wildatheart1232016-10-24

I added the hex files for the atmega328 as a binary release at Github

https://github.com/iDexe/videolight/releases

author
wildatheart123 (author)iDexe2016-10-25

Hi iDexe

Thanks for the HEX. But I already have another question ;)

Regarding the BMS: Is it really meant to be, that P+ and P- (besides the load and charger) are connected to the battery (like B+ and b- are connected to the battery)??

thanks

author
iDexe (author)wildatheart1232016-10-27

No, if I understand your question right. The batteries should not be connected with the output of the BMS again. On my BMS there are 5 wires for the batteries. Just connect them in series and attach the balancing leads in between the individual batteries. Then the BMS has 2 Contacts +, - wich are for charging/ discharging at the same time. They will just output the current battery voltage. So around 12-17V. You can use this to power your electronics. Don't attach your load directly to the batteries because you won't have short circuit protection and other nice things. For charging, just hook an external power supply that can deliver 18V or more to the + and - terminals. The BMS will automatically recognize it and switch to charging mode. Imagine having a Battery pack system that is entirely closed. It has only 2 leads coming out of it. Like these old NiMh packs for RC cars.

author
wildatheart123 (author)iDexe2016-10-28

Thanks again iDexe. I Have another BMS, so the connections are probably different. But I'll find the correct connection.

Once again another question ;)

My rotary switch is not working (the button does). The connection on the ATMEGA328, DT on Pin 6 (PD4) and CLK on Pin 11 (PD5) are correct, right?

thanks alot!

Laurin

author
iDexe (author)wildatheart1232016-10-29

No, the Rotary Encoder should be wired according to the pins in the code. Correct is DT on arduino pin 2 aka PD2 and CLK on arduino pin 3 aka PD3. These are Hardware pins 4 and 5 of the atmega328. Here is a nice oversight over the pins https://www.arduino.cc/en/Hacking/PinMapping168

author
wildatheart123 (author)iDexe2016-11-14

Hi iDexe, I finished the light and it works very well. I have another question though: Is it possible that the LEDs are not at full brightness (due to the code) when the dimmer is at 100%? I'm asking because I had some strips connected directly to my 12V Supply and they seemed to be brighter then.

author
iDexe (author)wildatheart1232016-11-14

Hey, cool congratulations. They are indeed not at full brightness. It's so that you can change the color with constant brightness. However the special insane mode should provide you with maximized brightness and color control. (By now the color control in this mode is not properly implemented. But if i find some time later this year i will fix this.) Also if you are finished it would be very cool to see your finished build here under "i made it". Im looking forward to see how you made it!

author
wildatheart123 (author)iDexe2016-11-14

Thanks once again for your quick reply! I'll try out the "insane mode" more deeply. I'll post pictures of my design. I actually added some self milled holders (anodized aluminum) by which I can put a diffusor in front of the LEDs. I also plan to build another light with 400mm x 300mm dimension.

author

Hi iDexe

For the large Design of the panel, I'd like to use a 1.3" oled I2C (128x64) display. Do you know what kind of changes need to be done in the code for that? Thanks!

author
iDexe (author)wildatheart1232016-11-27

Hmm, theoretically this should work. I was careful structuring the code. I made a class that builds the menu and handles the screen. Maybe its just enough to change the used screen identifier (i use u8glib). It specifies the resolution the communication (I2C or SPI) and the behavior of the reset pin (if existent). See the u8glib documentation for al the identifiers. If the outcome won't look nice take a look at the menu class and see if you can change some parameters to fit your screen.

What could be a problem is using a much larger font, because the atmega328 has only 32Kb of memory and its pretty much full. Then you might have to comprise in some way or use an other micro-controller. Also you can get rid of the Arduino boot loader to save some space.

author
wildatheart123 (author)iDexe2017-06-11

Hi iDexe. I built the large light with a 1.3" display. As you expected I'm now having some problems. The display response is now very slow. I tried it without the bootloader (as you proposed). I now try to play around with the code but I can't compile it. I always get several errors in connection with the u8glib librairy. Do you know what to do? Thanks!

C:\Users\Laurin\Desktop\VideoLight1.3\VideoLight1.3.ino:191:56: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

char *menu[] = {"VIDEO", "INSANE", "PORTION", "HALOGEN"};
^
C:\Users\Laurin\Desktop\VideoLight1.3\VideoLight1.3.ino:191:56: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

C:\Users\Laurin\Desktop\VideoLight1.3\VideoLight1.3.ino:191:56: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

C:\Users\Laurin\Desktop\VideoLight1.3\VideoLight1.3.ino:191:56: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

C:\Users\Laurin\Desktop\VideoLight1.3\VideoLight1.3.ino: In member function 'void Screen::renderChanges()':

C:\Users\Laurin\Desktop\VideoLight1.3\VideoLight1.3.ino:728:104: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

char *menu1[] = {"VIDEO", "INSANE", "PORTION", "HALOGEN", "STROBE", "MORSE", "FLICKER", "TORCH"};

C:\Users\Laurin\Desktop\VideoLight1.3\VideoLight1.3.ino:728:104: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

C:\Users\Laurin\Desktop\VideoLight1.3\VideoLight1.3.ino:728:104: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

C:\Users\Laurin\Desktop\VideoLight1.3\VideoLight1.3.ino:728:104: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

C:\Users\Laurin\Desktop\VideoLight1.3\VideoLight1.3.ino:728:104: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

C:\Users\Laurin\Desktop\VideoLight1.3\VideoLight1.3.ino:728:104: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

C:\Users\Laurin\Desktop\VideoLight1.3\VideoLight1.3.ino:728:104: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

C:\Users\Laurin\Desktop\VideoLight1.3\VideoLight1.3.ino:728:104: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

libraries\U8glib\U8glib.cpp.o (symbol from plugin): In function `U8GLIB::initSPI(_u8g_dev_t*, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)':

(.text+0x0): multiple definition of `U8GLIB::initSPI(_u8g_dev_t*, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)'

sketch\U8glib.cpp.o (symbol from plugin):(.text+0x0): first defined here

libraries\U8glib\U8glib.cpp.o (symbol from plugin): In function `U8GLIB::initSPI(_u8g_dev_t*, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)':

(.text+0x0): multiple definition of `U8GLIB::initHWSPI(_u8g_dev_t*, unsigned char, unsigned char, unsigned char)'

sketch\U8glib.cpp.o (symbol from plugin):(.text+0x0): first defined here

libraries\U8glib\U8glib.cpp.o (symbol from plugin): In function `U8GLIB::initSPI(_u8g_dev_t*, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)':

(.text+0x0): multiple definition of `U8GLIB::initI2C(_u8g_dev_t*, unsigned char)'

sketch\U8glib.cpp.o (symbol from plugin):(.text+0x0): first defined here

libraries\U8glib\U8glib.cpp.o (symbol from plugin): In function `U8GLIB::initSPI(_u8g_dev_t*, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)':

(.text+0x0): multiple definition of `U8GLIB::init8Bit(_u8g_dev_t*, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)'

sketch\U8glib.cpp.o (symbol from plugin):(.text+0x0): first defined here

libraries\U8glib\U8glib.cpp.o (symbol from plugin): In function `U8GLIB::initSPI(_u8g_dev_t*, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)':

(.text+0x0): multiple definition of `U8GLIB::init8BitFixedPort(_u8g_dev_t*, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)'

sketch\U8glib.cpp.o (symbol from plugin):(.text+0x0): first defined here

libraries\U8glib\U8glib.cpp.o (symbol from plugin): In function `U8GLIB::initSPI(_u8g_dev_t*, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)':

(.text+0x0): multiple definition of `U8GLIB::initRW8Bit(_u8g_dev_t*, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)'

sketch\U8glib.cpp.o (symbol from plugin):(.text+0x0): first defined here

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board Arduino/Genuino Uno.

author
Yonatan24 (author)2016-10-17

Wow! There's so much coming from such a small panel!

This reminds me of my homemade SpectrumLED panel, I think you might like it (the spectrum is varied in a simpler method- Dimmers! ;)

author
wildatheart123 (author)2016-10-14

Hi, I like your design and I'd like to build it. But it seems to me that some info is missing. Like some values of resistors (except R6) and the connections of the display, rotary encoder, main switch, connections to the LEDs (JP 1-6). Or am I just too stupid? ;) Danke Dir!

author
iDexe (author)wildatheart1232016-10-15

Hey, yes you are right. I have added the missing resistor values and the instructions on how to program the atmega328 with Arduino IDE. Have fun building!

author
wildatheart123 (author)iDexe2016-10-15

Hi iDexe
Thanks for the additional info. That will help alot building it! You used 4000K (and not 3000K) and 6000K for your design right?

author
iDexe (author)wildatheart1232016-10-16

Oh i think i made a mistake. I used 3000K and 4000K. I originally bought the LED strips for general illumination so this is what i had. It semms i messed with the numbers in my code. 4000K is still a little bit warmer than sunlight. If you want something that can really match sunlight i would recommend using 6000K.

author
John Culbertson (author)2016-10-13

Reminds me of Kevin Baxter's new panels

https://www.videolights.com/

Just needs the ambient light temp sensor.

author
iDexe (author)John Culbertson2016-10-15

Wow that ambient light sensor is a nice feature to have! But that kind of sensor is probably hard to get.

author
John Culbertson (author)2016-10-13

Great project, love the GUI!

author
Swansong (author)2016-10-13

It looks great :) Thanks for sharing!

About This Instructable

4,649views

73favorites

License:

More by iDexe:DIY portable Video Light
Add instructable to: