SparkFun Forums 

Where electronics enthusiasts find answers.

Discussions on the software and hardware for Atmel's STK standard.
By ghost_117
#149717
New user here, and I need some serious help. I'm using an atmega168 to create a parking lot management tool. It has a flexforce sensor and photoelectric sensor (similar to a garage door sensor) as a way of seeing when a car enters or exits the lot. I'm using the ADC pins since the sensors give out a strictly analog signal and have set up my code as such so that it displays out to an LCD, which I will also be connecting wireless with a pair of Xbees. My code is as such:
Code: Select all
void adc_init()
{
        ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); //Enable ADC and set 128 prescale
}

int main(void)
{
	ADCSRA |= 1<<ADPS2;
	ADMUX |= 0<<REFS0 | 0<<REFS1;
	ADCSRA |= 1<<ADIE;		//enables the use of interrupts for the program
	ADCSRA |= 1<<ADEN;		//ADC enabled
	
	sei();

	ADCSRA |= 1<<ADSC;
	
	
    while(1)
	{
	}
}	
	ISR(ADC_vect)
	{
		uint8_t Entrance = ADCL;
		uint16_t Exit = ADCH<<8 | Entrance;

		lcd_init();
		FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);		//these functions are included in lcd.c and lcd.h to initialize the LCD
		lcd_home();
	

		uart_init();
		FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);			//these functions are in the UART include files and are used to send data from the uart to the lcd
		stdin = stdout = &uart_stream;

		int x = 0;

		switch (ADMUX)
		{
			case 0xC0:
						++x;	//increment the counter to show a vehicle passed
						fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
						lcd_line_one();	//clears the other LCD rows so that the output is only on the first line of the LCD
						PORTB |= (1<<PB0);
						delay_ms(10);
						PORTB &= ~(1<<PB0);
						ADMUX = 0xC1;
						break;
						
			case 0xC1:
						--x;
						fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
						lcd_line_one();
						PORTB |= (1<<PB1);
						delay_ms(10);
						PORTD &= ~(1<<PD1);
						ADMUX = 0xC0;
						break;
						
			default:
						//Do nothing
						break;
		}
		 
	ADCSRA |= 1<<ADSC;
	
	}


So I ran an Isis simulation using pot resisters as the two sensors, but I can't get anything to run and nothing is displaying on the LCD. What am I doing wrong? :?:
By n1ist
#150027
ISRs should be "lean and mean". In general, they should set flags, toss data into ringbuffers, and wiggle bits. Everything else should be in the main loop. Certainly no delays or function calls, especially ones with large delays in them like the lcd calls.

You have uart_init() and lcd_init() in there; both should be in main(), as should the uart setup.
/mike
By stevech
#150059
yes. ISR should have just a few lines of code. Fast. Lean Mean.
THe non-ISR code should look at the ISR flags that were set and react, and finish this before the next interrupt might happen, or queue of the work to deal with bursts.

But as a Novice, you should do a small version of this problem without using any interrupts. Just have the main loop poll/check the I/O bits rapidly enough to catch events. If those events are like tens per second or slower, you can get by without interrupts - except for possible slowness of the LCD code, esp. if it has loops in it. If so, you need to choose a different LCD or somehow make it interrupt based, or use a serial port LCD that won't hog the CPU, etc. But the crummiest LCD product/code probably finishes most all LCD work in 0.1 sec or less. Maybe that's good enough.

This kind of analysis early in the design stage - leads to choosing the right hardware, and the right software approach. Your prof will respect the disciplined approach as to unbridled hacking.
By directory
#154205
‘ghost_117’, your coding part is just perfect. I understood that you are using an analog to digital converter here in series with your digital output, which is an LCD. This must work fine. There is always a chance of loose connections. This may sound like child’s play, but check it and ping me back! Thank you!



Ellery
---------------------------------------------
For outlook issues- Outlook Express help
Last edited by directory on Mon Dec 09, 2013 11:52 pm, edited 1 time in total.
User avatar
By thebecwar
#154905
A couple things I notice:

1) Why is your switch statement using ADMUX? And why are you changing which ADC channel you're using?
2) Do you ever use the variables entrance and exit?
3) Your count variable 'x' will be reset to 0 every time the interrupt fires.
4) What does the input look like? Have you considered building a comparator to convert the voltages into a signal you can read digitally?