Go Down

Topic: Room lighting with nano, pwm, relays, photo diodes (Read 168 times) previous topic - next topic

noobydev

Nov 25, 2017, 11:58 pm Last Edit: Nov 26, 2017, 12:13 am by noobydev
Hey all,

first of all, I'm German, my english is... well... not that good. Please be patient.
I'm new in the world of Arduino especially the nano. I already realized some small projects with a Raspberry Pi and my bachelor thesis was about programming an easy webserver which reads/writes to an I/O device.

My wife wants to get a "new" living room and I have to deal with it. She wants some indirectly lighting; bright, color-temperature adjustable and in addition some light spots for the dinning table.

Here are the preconditions:
  • One push button switch (230V) for all switching activities
  • One 5m 2 channel LED Stripe. 24V, 2 "colors", one color with 42W and the other with 28W. The stripe shall be dimmable and it shall use the possibility to change the color temperature
  • 4 oder 5 "gu10" LED Spots (230V)


What the Arduino nano shall do:
  • 1st push: LED Stripe with little brightness and a warm color temperature, gu10 lamps off
  • 2nd push: LED stripe with high brightness and a colder color temperature, gu10 off
  • 3rd push: nothing changed from 2nd push at LED stripe, but pu10 spots turn on
  • 4th push: all off


I can't draw circuit plans, so I have to describe everything, sry...
  • I want to use one arduino which will be sourced by a mobile phone power adapter.
  • Checking the 230V wall-Push-button: A 230V Signal lamp with a photo diode as input for the arduino.
  • I will use 2 PWM Pins of the arduino for 2 IRFZ48NPBF transistors, which will turns on and off the power (PWM...) from a 24V LED power adapter. I know, I have to think about pull down resistors. I need two transistors to set the 2 channels of the LED stripe independent to modify the color temperature.
  • In addition, 2 digital pins will be connected with a 2 channel 230V relay which will switch the 24 V power adapter (source of the LED Stripe) and the 230V for the gu10 LED spots.


My questions:
  • Is an Arduino able to use 2 PWM ouputs at the same time and to monitor one analog input with high enough resolution for getting all inputs and a switch bouncing preventing routine? Without flickering?
  • Shall I think about an important point which I didn't mentioned above?
  • Can you give me any code which I can use for some routines of my project?


edit: added "nano"
Thank you very much for reading my stuff.

6v6gt

Quote
I can't draw circuit plans, so I have to describe everything.
Even a picture of a hand drawn diagram showing the major components would be good start.
Consider also using a cheap multi button infrared remote control to switch the light instead of using a wall switch.

wvmarle

The LED strips: some come with built-in controller chips, and can be controlled more directly. They of course cost more. Then the Arduino just tells the strip the brightness and colour it has to show, and the strip takes care of that. Makes the hardware part a lot easier.

Relay: consider using solid state relays. Unless you like the clicking noise.

I second the remote control idea. It's also a lot more flexible to be able to control your LED spots and the strip independently, instead of having to cycle through a number of programs.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

noobydev

#3
Dec 07, 2017, 04:16 pm Last Edit: Dec 07, 2017, 10:10 pm by noobydev
Hey guys, sry for being away such a long time. Thanks for your advice, I wont to giv esome feedback:

An aditional remote was a nogo for me. We hat remotes. And yes, we need more than one light setting.

I got it to work, but I can't update my rduino anymore, because I destroyed my USB-TTL Adapter...

I want to post my code, its still not tested.

In the future, I want to integrate an XBee connection to controll the light via an self build remote conroll, which also controlls the home cinema.

Code: [Select]


#include <Bounce2.h>      // See https://github.com/thomasfredericks/Bounce2/wiki
#include <EEPROM.h>


const int programs = 5;                      // Number of light programs
const int eeprom_start = 10;                 // First adress for EEPROM access. Max 1023 minus programs * 3
const unsigned long time_debounce = 100;     // time needed for debounce the push button
const unsigned long time_setup = 5000;       // time needed for press push button to enter setup-mode

/*
 * Just some variables for manipulating the delay between
 * two brightness steps in setup-mode
 */
const int delay_faktor = 10;                 // delay_faktor * (delay_minuend - i / delay_divisor)
const int delay_minuend = 50;                //
const float delay_divisor = 2.0;             //

/*
 * Pin-Configuration:
 * Important to use pin 3 and 11. In setup, the neccessary CPU registers
 * for phase correct PWM were set for these 2 pins. For details: https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM
 *
 */

const int input = 12;               // Input from the optocoupler
const int SpotRelaisPin = 8;        // Controll output to 230V AC relay for turning LED spots on/off
const int transformer = 7;          // Controll output to 230V AC relay for turning LED-stripe transformer on/off
const int LEDchannel1 = 3;          // First channel of LED stripe
const int LEDchannel2 = 11;         // Second channel of LED stripe


/* byte LED[(programs) * 3];
 * Array that contains the brightness-values for all LED at all program states
 *
 * Structure:
 * Program  |  LED channel 1  | LED channel 2 | LED Spots
 *    0     |          0               1             2
 *    1     |          3               4             5
 *    2     |          6               7             8
 *    n     |       (3 * n)       (3 * n + 1)   (3 * n + 2)
 *            Values in table-content above represent the index of the array.
 */
byte LED[(programs) * 3];       

byte program = 0;               // counter for active light program

unsigned long time_pushed = 0;         // Point of time, when push button was closed last time
unsigned long time_released = 0;       // Point of time, whan push button was opened last time


/* const unsigned long max_long = ~((unsigned long)0);
 * 
 * stores the highest possible value of millis() before it overflows.
 * Max value is 2^32 -1 bit (4,294,967,295).
 * See https://www.arduino.cc/reference/en/language/functions/time/millis/
 *
 * This constant is used to check variables for reching the limit of
 * unsigned long and start routines that prevent logic errors.
 *
 */
const unsigned long max_long = ~((unsigned long)0);

Bounce deb_input = Bounce();
 

void setup()
{
  deb_input.interval(time_debounce);
  pinMode(input, INPUT);                            //-------------
  pinMode(SpotRelaisPin, OUTPUT);
  pinMode(transformer, OUTPUT);                     // Set all needed Pins to In or out
  pinMode(LEDchannel1, OUTPUT);
  pinMode(LEDchannel2, OUTPUT);                     //-------------
  deb_input.attach(input);
 

/*
 * The following two lines will preset the registers in Atmega 328 to
 * phase correct PWM at pins 3 and 11.
 *
 * Just modifying OCR2A (0-255) will configure pin 3
 * Just modifying OCR2B (0-255) will configure pin 11
 *
 * For details: https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM
 *
 */
  TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM20);  // Initialising of phase correct PWM
  TCCR2B = _BV(CS22);                               // for pins 3 and 11
 
  digitalWrite(transformer, HIGH);                  // Make sure that both channels to the relay are HIGH
  digitalWrite(SpotRelaisPin, HIGH);                // The relay will switch, if the output is LOW
  for(int i = 0; i < (programs * 3); i++)           // Read the full program from the EEPROM. This prevents from
    LED[i] = EEPROM.read(eeprom_start + i);         // loosing configuration bye power loss (e.g. blackput)
}

/* blink_sequenz
 *  int n - number of iterations
 * 
 *  Just blink that often, which LED you are going to program:
 *  1, 2 or 3.
 * 
 */
void blink_sequenz(int n)
{
  for (int i = 0; i < n; i++)
  {
    if (i != 0) delay(1500);
    LED[(program * 3) + 0] = 255;
    LED[(program * 3) + 1] = 255;
    LED[(program * 3) + 2] = 1;
    set_led();
    delay(1500);
    LED[(program * 3) + 0] = 0;
    LED[(program * 3) + 1] = 0;
    LED[(program * 3) + 2] = 0;
    set_led();
    if (i == n) delay(1500);
  }   
}

/*
 * save_program
 *
 * Stores the LED brightnesses of actual program to the EEPROM
 * via EEPROM.uptdate
 *
 */
void save_program()
{
  for(int i = program * 3; i < program * 3 + 3; i++)
    EEPROM.update(eeprom_start + i, LED[i]);
}


/*
 * set_led();
 *
 * The function wich set all the outputs and manipulates the CPU-PWM registers.
 *
 * It reads the actual program and actual brightnes values from
 * LED[program+[1,2,3]]
 *
 */
void set_led()
{
  if(program == 0){
    digitalWrite(SpotRelaisPin, HIGH);
    digitalWrite(transformer, HIGH);
    return ;
  }
  if(LED[(program * 3) + 2] > 0)
    digitalWrite(SpotRelaisPin, LOW);
      else
    digitalWrite(SpotRelaisPin, HIGH);

  if(LED[(program * 3) + 0] > 0 || LED[(program * 3) + 1] > 0)
    digitalWrite(transformer, LOW);
  else
    digitalWrite(transformer, HIGH);

  OCR2A = LED[(program * 3) + 0];
  OCR2B = LED[(program * 3) + 1];

}


/*
 * int inputdelay(unsigned long wait)
 *
 * Waitung for wait milliseconds for any input
 *
 * If an input is recognized, the function aborts with return 1
 * before teh tim eis over.
 *
 * If no input occurs during waitung time, function returns 0.
 *
 */
int inputdelay(unsigned long wait)
{
  unsigned long now = millis();
  /*
   * This if is to prevent logical errors if millis() almost overflows.
   * It just delays the execution of the sketch to wait for the overflow
   * before continue the sketch
   */
  if(max_long - wait < now)
  {
    delay(wait + 2);
    now = millis();
  }
 
  while(now + wait <= millis())
  {
    deb_input.update();
    if (deb_input.rose())
    {
      while(!deb_input.fell())
      {
        delay(5);
        deb_input.update();
      }
      return 1;
    }
  }
  return 0;
}


/*
 * int pwm_setup(int set_temp)
 *
 * This function just increase (0 to 250) and decrease (250 - 0)
 * the brightness of one LED-stripe and wait for an acknowledge (input) of some brightness
 * via inputdelay().
 *
 * It runs infinite till some input is recognized via inputdelay() and returns always 1.
 *
 */
int pwm_setup(int set_temp)
{
  while(1)
  {
    for (int i = 0; i < 26; i++)
    {
      LED[(program*3)+set_temp] = i * 10;
      set_led();
     if(inputdelay(delay_faktor * (delay_minuend - i / delay_divisor)))
       return 1;
    }
 
    for (int i = 25; i == 0; i--)
    {
     LED[(program*3)+set_temp] = i * 10;
     set_led();
     if(inputdelay(delay_faktor * (delay_minuend - i / delay_divisor)))
       return 1;
    }
  }
}


/*
 * void setup_led()
 *
 * This function manages the call of other functions in order to
 * change the actual LED program.
 *
 */
void setup_led()
{
  int set = 0;

  while(set < 2)
  {
    blink_sequenz(set+1);
    set += pwm_setup(set);
  }
 
  blink_sequenz(set+1);
  while(set < 3)
  {
    LED[(program*3)+set] = !LED[(program*3)+set];
    set_led();
    if(inputdelay(1500))
      set++;
  }
  save_program();
}


/*
 * void loop()
 *
 * Main function of all arduino sketches.
 * It checks the input continuously and increasy program counter by 1 if
 * Push button is pushed, released and waited for end of debounce time.
 *
 * If button is pushed and hold for time_setup milliseconds, setup_led() will
 * edit the actual program.
 */
void loop()
{
  int change;
  if(max_long - (time_setup + 500) <= millis())
    delay(time_setup + 1000); 
 
  change = deb_input.update();
 
  if (deb_input.rose())
    time_pushed = millis();

  if (deb_input.fell())
  {
    if(program < programs - 1)
      program++;
    else
      program = 0;

    set_led();
  }

  if (millis() - time_pushed >= time_setup && !change)
    setup_led();
}




My wife loves the new lamp  :)

Go Up