Intelligent Lighting Control using AVR Microcontroller

May 12th, 2012 | by | technology

May
12

This dissertation is an effort to learn embedded system development and embedded programming using AVR microcontroller.

This dissertation will look at the working of Analog to Digital conversion (ADC) and the usage of Pulse Width Modulation (PWM) for Digital to Analog conversion (DAC). This dissertation will also cover the features of AVR microcontroller and the usage of timers and ADC conversion in AVR microcontroller.

This dissertation will combine the Analog to Digital conversion (ADC) and Pulse Width Modulation (PWM) to create an intelligent lighting, which will be automatically controlled based on the external ambient lighting. So, at dusk, when the external sunlight gradually decreases, the intelligent light will start, and it brightness will start gradually increasing to its maximum. Similarly, at dawn, the first appearance of light in the sky before sunrise, the intelligent light will slowly start dimming and will automatically switch off in the morning.

#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>

// initialize adc
void adcInit()
{
  // AREF = AVcc
  ADMUX = (1<<REFS0);

  // ADC Enable and prescaler of 128
  // 8000000/128 = 62500
  ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}

// read adc value
uint16_t adcRead(uint8_t ch)
{
  // select the corresponding channel 0~7
  // ANDing with '7' will always keep the value
  // of 'ch' between 0 and 7
  ch &= 0b00000111;  // AND operation with 7
  ADMUX = (ADMUX & 0xF8)|ch;   // clears the bottom 3 bits before ORing

  // start single conversion
  // write '1' to ADSC
  ADCSRA |= (1<<ADSC);

  // wait for conversion to complete
  // till then, run loop continuously
  // The loop does nothing while ADIF is set to 0,
  // it exits as soon as ADIF is set to one,
  // i.e. conversion is complete.
  while(!(ADCSRA & (1<<ADIF)));

  //Clear ADIF by writing one to it
  ADCSRA|=(1<<ADIF);

  return (ADC);
}

void pwmInit()
{
   /*
   TCCR0 - Timer Counter Control Register (TIMER0)
   -----------------------------------------------
   BITS DESCRIPTION

   NO:   NAME   DESCRIPTION
   --------------------------
   BIT 7 : FOC0   Force Output Compare [Not used in this example]
   BIT 6 : WGM00  Wave form generation mode  [SET to 1]
   BIT 5 : COM01  Compare Output Mode    [SET to 1]
   BIT 4 : COM00  Compare Output Mode    [SET to 0]

   BIT 3 : WGM01  Wave form generation mode  [SET to 1]
   BIT 2 : CS02   Clock Select         [SET to 0]
   BIT 1 : CS01   Clock Select         [SET to 0]
   BIT 0 : CS00   Clock Select         [SET to 1]

   The above settings are for
   --------------------------

   Timer Clock = CPU Clock (No Prescalling)
   Mode    = Fast PWM
   PWM Output  = Non Inverted

   */

   TCCR0|=(1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00);

   //Set OC0 PIN as output. It is  PB3 on ATmega16 ATmega32

   DDRB|=(1<<PB3);
}

/******************************************************************
Sets the duty cycle of output. 

Arguments
---------
duty: Between 0 - 255

0 = 0%

255 = 100%

The Function sets the duty cycle of pwm output generated on OC0 PIN
The average voltage on this output pin will be

         duty
 Vout=  ------ x 5v
         255 

This can be used to control the brightness of LED or Speed of Motor.
*********************************************************************/

void setPWMOutput(uint8_t duty)
{
   OCR0=duty;
}

int main()
{
  uint16_t adcResult;
  uint8_t pwmBrightness;

  // initialize adc and pwm
  adcInit();
  pwmInit();

  _delay_ms(50);

  while(1)
  {
    adcResult = adcRead(0);    // read adc value at PA0

    // Mapping the adc value in the range of 0-1024 (2^10 bits)
    // to 0-255, which can be sent to 8 bit OCR0 register.
    // So the adcResult is divided by 4, to make it in the
    // range of 0-255.
    // After that the value is subtracted from 255, so that if
    // the adc value is less, we want to send high value to the
    // OCR0, for increasing brightness, and if the adc value is
    // high, we want to send lower values for the PWM signal
    // generation, to reduce the brightness of the LED.
    pwmBrightness = (uint8_t)(255 - (adcResult/4));

    //Send the pwm value to the OCR0, to control the LED brightness
    setPWMOutput(pwmBrightness);
   }
}

The presentation and the project report can be downloaded from the previous post: Seminar on Embedded System Development using AVR Microcontroller.

No Comments »

Bipolar stepper motor controller using AVR microcontroller and L298N motor driver

June 22nd, 2010 | by | technology

Jun
22

In this video, we’ll see how to control the bipolar stepper motor using the AVR ATMega32 microcontroller and L298N motor driver. Both the motors ports A & B are enabled, by connecting the EnableA and EnableB lines to PB0 and PB1 respectively. Both the PB0 and PB1 pins are always at high volatge. The input lines of the L298N motor driver board 1,2,3,4 are connected to Port PB7, PB6, PB5, PB4 respectively. Now, the voltage is varied on the input lines of the L298N motor driver using the ATMega32 microcontroller, causing the change in voltage at the motor input lines, i.e., the L298N motor driver output lines. This causes the stepper motor to rotate.

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  DDRB=0xFF;
  while(1)
  {
    //Normal Bipolar Stepping
    PORTB = 0b10010011;
    _delay_ms(10);
    PORTB = 0b01010011;
    _delay_ms(10);
    PORTB = 0b01100011;
    _delay_ms(10);
    PORTB = 0b10100011;
    _delay_ms(10);
  }
}

No Comments »