problems using attiny104 for blind working stick

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi every one. I have a problem conserning a project and i hope you'll help me with it. I'm doing a blind wlaking stick usint attiny104, IR sensor 2y0a02(connected on pin PB3) and a LED(connected on pin PA0). For now i want that the closer i get to an object, the faster the LED will blink. firstlly, when i mouve from one distance to another, the LED must blink faster or slower directly but instead, there is a delay before the blinking rate changes and it is not stable. My first question is how can i solve that and secondly, how can i see the value coming from my IR sensor. this is my code. I'm using Atmel Studio7

#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>

#define SetBit(x,y) (x|=(1<<y))
#define ClrBit(x,y) (x&=~(1<<y))
#define TestBit(x,y) (x&(1<<y))

uint32_t adc_value;
void ADC_Init(void);
void timer_init(void);

void timer_init(void)
{
	TCCR0B |= (0 << WGM03)|(1 << WGM02)|(0 << WGM01)|(0 << WGM00); //CTC mode
	TIMSK0 |= (1 << OCIE0A);
	sei();
	TCCR0B |= (1 << CS02)|(0 << CS00); // prescale at 1024
}

void ADC_Init(void){
	//ADCSRA |= (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADATE); // enable adc interrupt // Set ADC prescalar to 64 - ~115KHz sample rate @ 7372800MHz and set ADC to Free-Running Mode
	ADCSRA |=  (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADATE);

	ADMUX |= (0 << REFS0) | (0 << REFS1); // Set ADC reference to VCC
	ADMUX |= (1 << MUX2) |(1 << MUX1) |(1 << MUX0);//enable adc on pin PB3
	ADCSRB |= (0 << ADLAR); //adlar - right ajustment
	ADCSRA |= (1 << ADEN);  // Enable ADC
	ADCSRA |= (1 << ADIE); // activate interruptions at the end of conversion
	sei(); // On active les interruptions
	ADCSRA |= (1 << ADSC);  // Start AD Conversions

}

ISR(ADC_vect)
{
	adc_value = ADCL; // takes the value of the low register(8 bits LSB)
	adc_value |= ((uint16_t) ADCH << 8); // takes the value of the upper register( 2 bits MSB)

	if(adc_value < 0x100) // if the distance is lower than 0x100 (256)
	{
		OCR0A = 1000; // set the timer compare value
	}
	else if((adc_value < 0x200) && (adc_value > 0x100))// if the distance is between 0x100 (256) and 0x200 (512)
	{
		OCR0A = 10000;// use another compare value
	}
	else
	{
		OCR0A = 20000;// another compare value
	}

	ADCSRA |= (1 << ADSC); // restart the conversion
}

int main(void)
{
	//to use the correct clock frequency of the attiny104 (8Mhz) cuz attiny104 is by default F_CPU/8
	CCP = 0xD8;
	CLKPSR = 0x00;

	// port a as output tu use the LED
	DDRA |= (1 << PA0);

	ADC_Init();
	timer_init();

	while(1){}
}

ISR(TIM0_COMPA_vect)
{
	PORTA ^= (1 << PA0); // toggle the led
}

thanks

 

 

 

 

Njampa2008+

Last Edited: Wed. Dec 27, 2017 - 01:51 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

You need to break this into separately testable modules rather than putting it all together and then trying work out which bit is failing. Test the sensor reading separately. Test the timer/LED flashing separately and so on.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kouros wrote:
i want that the closer i get to an object, the faster the LED will blink
  Can you put a specification on that?, i.e.  distance x = what blink rate

Without a spec, how do you know when it is met?  In other words, how do you define what working means?

Clawson's advice is spot on!  +1

 

Jim

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A couple of additional notes,

 

Why all the "|="  RMW operations in the ADC init, just set the registers with a single "=" to a known value.

 

Since adc_value is shared between main() and ISR(), it must be declared volatile.

 

When reading the ADC data registers, the compiler knows how to read the two registers H/L, so you can just use:

 

adc_value = ADC;   or perhaps

adc_value = ADCW;

 

 

Sounds like a worth while project, good luck with it.

 

Jim

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I fail to see why you run the adc in free running mode and use interrupts. Surely updating the flash rate at any more than 10 times a second is useless.