loading

Whats wrong with my code and hardware for this emergency light?

I am making this emergency light which comes on when theres no power and the light is low...
I use an LDR to detect the light level and an external 3 volt power supply wall adapter to see if the power is on or not...
i am using the ADC  here, but I guess there might be something wrong with my idea... :( the ldr is connected to ADC0 and the 3V supply to ADC3. The schematic is attached...
it reads the ADC0 result only  when the ADC3 is not connected otherwise it returns the result of ADC3.

I have also attached the code, see and spot something I couldnt understand... It has been taken in bits and pieces from other codes but I cant understand what the problem is,.... :(

#include <avr/io.h>

#include <avr/interrupt.h>
#define F_CPU 800000
#include <util/delay.h>






void disp(int i)
{
switch (i)
{
case 1: PORTD = 0b10110111;break;
// 76543210
case 2: PORTD = 0b11000010;break;
// 76543210
case 3: PORTD = 0b10010010;break;
// 76543210
case 4: PORTD = 0b10110100;break;
// 76543210
case 5: PORTD = 0b10011000;break;
// 76543210
case 6: PORTD = 0b10001000;break;
// 76543210
case 7: PORTD = 0b10110011;break;
// 76543210
case 8: PORTD = 0b10000000;break;
// 76543210
case 9: PORTD = 0b10010000;break;
// 76543210
case 0: PORTD = 0b10000001;break;
// 76543210
default:PORTD = 0b11111110;break;
}
}
void dispLeft(int i)
{
PORTB = 0b00000001;
disp(i);
_delay_ms(2);
}
int dispRight(int i)
{
PORTB = 0b00000010;
disp(i);
_delay_ms(2);
return(i);
}


void InitADC()
{
ADMUX=(1<<REFS0); // For Aref=AVcc;
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); //Prescalar div factor =64 =>8MHz/64=125kHz
}
//|(1<<ADPS0)
uint16_t ReadADC(uint8_t ch)
{
//Select ADC Channel ch must be 0-7
ch=ch&0b00000111;
ADMUX|=ch;

//Start Single conversion
ADCSRA|=(1<<ADSC);

//Wait for conversion to complete
while(!(ADCSRA & (1<<ADIF)));

//Clear ADIF by writing one to it
//Note you may be wondering why we have write one to clear it
//This is standard way of clearing bits in io as said in datasheets.
//The code writes '1' but it result in setting bit to '0' !!!

ADCSRA|=(1<<ADIF);

return(ADC);
}

void Wait()
{
uint8_t i;
for(i=0;i<20;i++)
_delay_loop_2(0);
}

void switch_toggle(int swtch)
{
switch (swtch)
{
case 0 : PORTB=0b00000000;
break;
case 1 : PORTB=0b00000100;
break;

}
}


void main()
{

uint8_t power_state;
uint16_t ldr_result = 512;
uint16_t power_result = 512;
//Initialize ADC
InitADC();
DDRD = 0b11111111;
DDRB = 0b00000111;


int count = 200;
while(count)
{
PORTB = 0b00000001;
PORTD = 0b10001110; //O
_delay_ms(2);
PORTB = 0b00000010;
PORTD = 0b10101110; //n
_delay_ms(1);
count--;
}


while(1)
{



// Read Analog value from channel-0 and 3
ldr_result=ReadADC(0);
_delay_ms(500);
power_result=ReadADC(3);

uint16_t to_disp = ldr_result;
uint8_t t1[4];
int i=3;
while(i>=0)
{

t1[i] = to_disp%10;
to_disp/=10;
i--;
}
i=0;
while(i<=3)
{
int count = 100;
while(count>0)
{
dispRight(t1[i]);
_delay_ms(1);
dispLeft(t1[i-1]);
_delay_ms(1);
count--;
}
i++;
}


if(power_result>100)
{
power_state=1;
}
else
{
power_state=0;
}
if(power_state==1)
{
switch_toggle(0);
}
else
{

if(ldr_result>300)
{

switch_toggle(0);
}

else
{
switch_toggle(1);
}
}
} //while

} //main

sort by: active | newest | oldest
trubshac7 years ago
Your problem is in ReadADC(). You sensibly mask out all but the bottom 3 bits of the channel number (ch=ch&0b00000111), but then you OR the result with the current value of ADMUX (ADMUX|=ch;). So, when you call ReadADC(0) it correctly selects channel 0, then you call ReadADC(3), and it correctly sets channel 3, then you call ReadADC(0) again but this time, the bottom 2 bits of ADMUX are still set from the previous call, you are just ORing it with 0, so channel 3 gets set again. To fix this, you need to clear the channel select bits of ADMUX before ORIng in the new bits. This can be done with ADMUX = (ADMUX & 0xF8) | ch;
pro2xy (author)  trubshac7 years ago
Hahaha!!! It worked brilliant, but must have been one of my bad luck days... ;) Everything worked great, I plugged in the main power from my UPS battery (12v) and powered the micro through a 7805.... It went well. But it has been raining here for a few days and maybe the earthing in the house is very wet, I dunno what was happening. I could feel a bit of potential whn I was soldering, but I didnt pay much attention. Then I connected my ups bttery to the stuff and powered on, and the moment I touched the connectiions on the circuit that I had made I got a very nasty shock... well, I ignored it again, and got another one.. So I thought I should connect a wire from the 7805 ground to the my house's ground.. And when I was soldering this wire to the 7805 and there was a bright spark and it blew up......... :'( So here crashed my dreams.... :'( Any idea why that happened? Shal I make an instrucatable of it?? I dont have the pics though.. :(
mrwolfe pro2xy6 years ago
I'd double check to make sure you don't have the active and earth switched in your circuit. Leaky house earths won't cause bright flashes, but connecting the active to the earth will!
rickharris7 years ago
http://www.picaxe.com  Oh so much easier and little more cost with a Picaxe micro

Start:
readadc 1.B1  'reads the valuse returned by the LDR on pin 1 into a variable B1
if B1< 150 then LEDON else LEDOFF  'evaluates the light level

goto start  ' jumps back to check again

LEDON:  ' turn LED on pin 4 on
High 4

goto start

LEDOFF: 'turn LED on pin 4 off.
Low 4
goto start
pro2xy (author)  rickharris7 years ago
But I'd like to learn about them .. :)
pro2xy (author)  rickharris7 years ago
HAHA!! You missed out the main thing... The light comes on only when the power is off AND the light level is low... ;) Anyway, I've never had a pic, and I don't know if I'm buying one very soon... :)
pro2xy (author) 7 years ago
Thanks TRUBSHAC I'll try this out and let you know how it goes... :) Well spotted, though... :D
pro2xy (author) 7 years ago
here, sorry
Pic-0107.jpg