ATMega8 auto-calibratable photosensor

Microcontroller, DSP and FPGA Topics

ATMega8 auto-calibratable photosensor

Postby SemiconductorCat » Sun Feb 09, 2014 2:35 pm

Hi I'm using ATMega8 on this project.
Code: Select all
     avr-gcc -g -Os -mmcu=atmega8 -c serial.c
     avr-gcc -g -mmcu=atmega8 -o serial.elf serial.o
     avr-objcopy -j .text -j .data -O ihex serial.elf serial.hex

      avrdude -p m8 -P usb -c usbasp -Uflash:w:serial.hex:i
      [@Mr. Thisara: please ignore the warning messages , refer drawing 1 for schematic.]
      Turns on the impression solonoid when paper cut the photo-resistor.
      Replace the old analog preset and auto calibrate .

     (c) Udara Type Setting Panadura.

#define F_CPU 16000000UL

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

void bit_set_portb(int bit)
  int mask = (1<<bit);
  PORTB = PORTB | mask;


int is_bit_set_portb(int bit)
  int mask = (1<<bit);
  int val = PINB & mask ;
  if( val ==0)
    return 0;
  return 1;

void adc_init(void){

ADCSRA |= ((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));    //16Mhz/128 = 125Khz the ADC reference clock
ADMUX |= (1<<REFS0);                //Voltage reference from Avcc (5v)
ADCSRA |= (1<<ADEN);                //Turn on ADC
ADCSRA |= (1<<ADSC);                //Do an initial conversion because this one is the slowest and to ensure that everything is up and running

uint16_t read_adc(uint8_t channel){
ADMUX &= 0xF0;                    //Clear the older channel that was read
ADMUX |= channel;                //Defines the new ADC channel to be read
ADCSRA |= (1<<ADSC);                //Starts a new conversion
while(ADCSRA & (1<<ADSC));            //Wait until the conversion is done
return ADCW;                    //Returns the ADC value of the chosen channel

void main()

  /* set port B I/O directions */
  /* PB1 - calibration progress LED */
  /* PB2 - calibration finished LED */
  /* PB3 - going to solonoid */
  /* PB4 - input , calibration switch */
  /* ADC0 - going to LDR input , LDR is pulled up with a 10K */
  DDRB = 0b00000111;

  int idle_value ;
  int delta ;
  idle_value = read_adc(0);
      static int analog_reading ;
    if(is_bit_set_portb(3)) /* PB3 is the calibration push button */
      idle_value = read_adc(0);

    /* read the analog again */
    analog_reading = read_adc(0);

    delta = analog_reading ^ idle_value ;
    if( delta >70){ /* magic value 70 means ,if we found more than 70 delta it should trigger */
      bit_set_portb(2); // PB2 is going to solonoid //
    _delay_ms(50); // * avoid some race conditions and bouncing effects */

My question are bellow.

* ATMega8 costs around 160/-Rs on the local market. What I need is a cheaper device , I know I could do this with pure analog design. But I also heard that there are very cheap micro-controllers there too. I'm planing on ATiny series.
I just need 3 GPIO and one analog input for this. I also need to know how much ?

* My second question is to implement the soft start solenoid algorithm. Where I could have two thread , one thread would read the analog value on that LDR connected pin and then change the state variable on thread 2. Then thread 2 will generate soft PWM on the solonoid. Is that a good design?  So that I need to keep a sine table inside the micro-controller?
Any other better way to do this?

* As you could see I have hardcoded the delta value to trigger and the debouncing time too.
 I've taken these values by experimenting. Is any dynamic method to get these values like auto calibration?
User avatar
Posts: 462
Joined: Mon Aug 22, 2011 3:12 pm
Cash on hand: 23,861.30
Location: currently in hyperspace

Invitations sent: 0
Registered friends: 0
Reputation point: 9

Return to Embedded Processors & Programming

Who is online

Users browsing this forum: No registered users and 1 guest