Attiny2313 analog comparator

Hello!

I just accidentally burnt out my atmega168 and all i have around the house is an Attiny2313. I read that the 2313 does not have an ADC, but it does have an analog comparator, which I think it is just what I need for my project. I need to see if a specific voltage is above or below a reference voltage. Does any of you have an Arduio IDE code for that? i only use the Arduino IDE for programming Atmega s and I am not familiar with other languages. Basically, if a value is below another value, digitalWrite(ledPin, LOW) and viceversa, that is what I need.

I would be grateful for any help. Thank you!

The 2313 can do this, but not as an Arduino. AFAIK, that chip isn't supported. You can use AVR C/C++ instead though, which is what the Arduino libraries are built on. You'll have to use direct I/O instead of digitalWrite, you'll put your code in main() instead of loop(), and you'll have to initialize all the hardware stuff yourself. Not a big deal if you're comfortable with regular C development and can read the datasheet. :slight_smile:

Download AVR Studio (free from Atmel's site) and follow some online AVR tutorials to get yourself started. Or just order a new ATmega chip.

It is fairly easy to program. Read the datasheet.

Hello!

claudiu_mirescu:
I just accidentally burnt out my atmega168 and all i have around the house is an Attiny2313.

Bummer.

I read that the 2313 does not have an ADC, but it does have an analog comparator, ...

That is correct.

Does any of you have an Arduio IDE code for that?

To add support for the 2313 to the IDE...
http://code.google.com/p/arduino-tiny/

Basically, if a value is below another value, digitalWrite(ledPin, LOW) and viceversa, that is what I need.

I think I have exactly what you need. I'll be back in a few minutes...

I can't remember what it does but at least you'll know how to initialize the comparator...

#include <avr/interrupt.h>
#include <TinyDebugKnockBang.h>

/*----------------------------------------------------------------------------*/

static const uint8_t AIN1 = 10;
static const uint8_t LED = 2;
static const uint8_t OUT = 7;

/*----------------------------------------------------------------------------*/

static volatile uint8_t capture;
static volatile bool gotvalue;

/*----------------------------------------------------------------------------*/

void setup( void )
{
  Debug.begin( 250000 );

  // Configure the pins
  pinMode( AIN1, INPUT );
  pinMode( LED, OUTPUT );
  pinMode( OUT, OUTPUT );

  // Disable the input driver on AIN1
//DIDR = DIDR | (1 << AIN1D);

  // Configure the comparator
  ACSR =
      (0 << ACD)     // Analog Comparator Disable
      | (1 << ACBG)  // Analog Comparator Bandgap Select
      | (0 << ACO)   // Analog Comparator Output
      | (1 << ACI)   // Analog Comparator Interrupt Flag
      | (0 << ACIE)  // Analog Comparator Interrupt Enable
      | (0 << ACIC)  // Analog Comparator Input Capture Enable
      | ((0 << ACIS1) | (0 << ACIS0));   // Analog Comparator Interrupt Mode Select: 0 0 Comparator Interrupt on Output Toggle.

  // Ensure the bandgap is ready for business (70us max)
  delay( 2 );

  // Ensure the capacitor is discharged enough for the comparator to output 1
  digitalWrite( LED, HIGH );
  digitalWrite( OUT, LOW );
  while ( (ACSR & (1 << ACO)) == 0 );
  digitalWrite( LED, LOW );
  
  // Enable the interrupt
  ACSR = ACSR | (1 << ACIE);

  // Kick start
  PORTD |= (1 << PORTD5);
}

/*----------------------------------------------------------------------------*/

static void Test1( void )
{
  uint16_t c1;
  uint16_t c2;
  
  c1 = 0;
  c2 = 0;

  digitalWrite( OUT, HIGH );
  while ( ! digitalRead( AIN1 ) )
    ++c1;

  digitalWrite( OUT, LOW );
  while ( digitalRead( AIN1 ) )
    ++c2;

  Debug.print( c1 );
  Debug.write( '\t' );
  Debug.print( c2 );
  Debug.println();

  digitalWrite( LED, ! digitalRead( LED ) );  
  delay( 100 );
}

/*----------------------------------------------------------------------------*/

static void Test2( void )
{
  uint16_t c1;

  c1 = 0;

  ACSR = ACSR | (1 << ACI);
  digitalWrite( OUT, HIGH );
  while ( (ACSR & (1 << ACI)) == 0 )
    ++c1;

  digitalWrite( OUT, LOW );

  Debug.print( c1 );
  Debug.println();

//  digitalWrite( LED, ! digitalRead( LED ) );  
  delay( 250 );
}

/*----------------------------------------------------------------------------*/

static void Test3( void )
{
  digitalWrite( OUT, HIGH );

  if ( ACSR & (1 << ACO) )
  {
    digitalWrite( LED, HIGH );  
  }
  else
  {
    digitalWrite( LED, LOW );  
  }
}

/*----------------------------------------------------------------------------*/

/**
ISR(ANA_COMP_vect)
{
  capture = TCNT1;
  gotvalue = true;
}
**/

static void Test4( void )
{
  uint8_t v1;
  uint8_t v2;

  gotvalue = false;
  digitalWrite( OUT, HIGH );
  while ( ! gotvalue );
  v1 = capture;

  gotvalue = false;
  digitalWrite( OUT, LOW );
  while ( ! gotvalue );
  v2 = capture;

  Debug.print( v1 );
  Debug.write( '\t' );
  Debug.print( v2 );
  Debug.println();

  delay( 250 );
}

/*----------------------------------------------------------------------------*/

ISR(ANA_COMP_vect)
{
  if ( ! gotvalue )
  {
    capture = TCNT1;
    gotvalue = true;
  }
}

static void Test5( void )
{
  uint8_t v;

  if ( gotvalue )
  {
    v = capture;

    gotvalue = false;

    if ( ACSR & (1 << ACO) )
    {
      PORTD |= (1 << PORTD5);
    }
    else
    {
      PORTD &= ~ (1 << PORTD5);
    }

    Debug.print( capture );
    Debug.println();
    delay( 100 );
  }
}

/*----------------------------------------------------------------------------*/

void loop( void )
{
  Test5();
}

/*----------------------------------------------------------------------------*/

Thank you very much, it was very kind of you to provide the solutions and the code. I will surely dig into it until a new Atmega168 arrives.

Let me tell you what I did with the last one. i accidentally connected a 470nF capacitor from VCC to ADC0. After that, i only get "Atmega not responding, check the connections and try again". I checked the connections, the progammers is ok, all I can think is that the Atmega168 burnt out consequently to the capacitor (which stayed there long enough before I figured it out). Is that possible?

Is that possible?

Maybe it is coincidental but I wouldn't give up hope.

claudiu_mirescu:
Thank you very much, it was very kind of you to provide the solutions and the code. I will surely dig into it until a new Atmega168 arrives.

The code is certainly a bit odd so I will understand if you have questions.

i accidentally connected a 470nF capacitor from VCC to ADC0. After that, i only get "Atmega not responding, check the connections and try again". I checked the connections, the progammers is ok, all I can think is that the Atmega168 burnt out consequently to the capacitor (which stayed there long enough before I figured it out). Is that possible?

I have no idea. But I'm will to bet the folks who hang out here can answer the question...
http://arduino.cc/forum/index.php/board,5.0.html

Here is what I would use:

/*
 */
//some chips use ana_comp_vect and others analog_comp_vect
#if defined(ANA_COMP_vect)
ISR(ANA_COMP_vect) {
#else
ISR(ANALOG_COMP_vect) {
#endif
	//clear the flag
	//_comp_isr_ptr();				//run user isr handler
        //insert your code here
        //example
        if (ACSR & (1<<ACO)) {//aco asserted. do something}
        else {//aco cleared. do something else}
}

//reset the comparator
void comp_init(void) {
	//ain0/ain1 assumed to be input

	//configure output pin

	//configure the analog comparator
#if defined(DIDR)
	DIDR = 	(1<<AIN1D) |			//disable ain1's digital input
			(1<<AIN0D)				//disable ain0's digital input
			;
#endif

#if defined(DIDR1)
	DIDR1 = (1<<AIN1D) |			//disable ain1's digital input
			(1<<AIN0D)				//disable ain0's digital input
			;
#endif

	//configure ACSRB if available
#if defined(ACSRB)
	ACSRB &=~(0<<ACME);				//disable acme
#endif

	//configure ACSR
	ACSR &=~(1<<ACIE);				//disable interrupt
	ACSR = 	(0<<ACD) |				//analog comparator power on
#if defined(ACBG)
			(0<<ACBG) |				//bandgap reference not selected. Use AIN1 for non-inverting input
#endif
			(1<<ACI) |				//clear acif by writing '1' to it
			(0<<ACIE) |				//interrupt not yet enabled
			(0<<ACIC) |				//analog comparator input capture disabled
			(0<<ACIS1) | (0<<ACIS0)	//interrupt on output toggle
			;

	ACSR |= (1<<ACIE);				//enable the interrupt

	//rest comp_ptr
}

In your code, you would need to run comp_init() to initialize the analog comparator module. After that, the processing of ACO is done in the isr.

The code is written to run a variety of mcus and with user-installed isr so if you want, you can delete some of the stuff that's not relevant to your module.

Ok, thanks! Although I am not inititated in this language, I am willing to learn it because it looks like much more than Arduino.

My local shop only has Atmega8 in stock, the 168 will be received next week. Do any of you have the boards.txt file for the Atmega8? I found this on the internet:

##############################################################

atmega8noxtal.name=ATmega8-noxtal @8MHz

atmega8noxtal.upload.protocol=stk500
atmega8noxtal.upload.maximum_size=7168
atmega8noxtal.upload.speed=38400

atmega8noxtal.bootloader.low_fuses=0xe4
atmega8noxtal.bootloader.high_fuses=0xc4
atmega8noxtal.bootloader.path=atmega8_noxtal
atmega8noxtal.bootloader.file=ATmegaBOOT.hex
atmega8noxtal.bootloader.unlock_bits=0x3F
atmega8noxtal.bootloader.lock_bits=0x0F

atmega8noxtal.build.mcu=atmega8
atmega8noxtal.build.f_cpu=8000000L
atmega8noxtal.build.core=arduino

...but I don't know if it is reliable, considering that 8MHz looks a bit large to me. Until now, except Arduino, I only used Atmega168 (the burnout one) and Attiny2313, at 1MHz, whithout external crystal. Could this board be ok or I might have signature problems at uploading? i am using uspasp programmer and Arduino 1.0.1.

Thank you!

Will you be clocking the ATmega8 with an external crystal or resonator? Or will you be using the internal oscillator?

Until now I only used the internal oscillator. I didn't use external because I didn't need it, the internal oscillator was enough for my projects. I purchased a crystal oscillator but I never used it.

Connecting a capacitor between "VCC to ADC0"

Two things could have taken place.....

1.. the Cap may have been charged to say 13volts, causing > 5v on the ADC 0
2.. if the Cap was not charged, the capacitor would slowly fill to the voltage rail, eg 5v

So does the board get any power, what still works with it? - a sudden voltage spike from a fully charged cap is the only thing that could have done any damage...

The cap was not charged, I just placed it between Vcc and ADC0, but I wanted to put it between ADC0 and GND. Not knowing what I have done, I connected the programmer and I got the message "Board not responding, check the connections." No matter how many times I checked, undid and did the connections, I still get this message. The board does nothing, even the previous sketch I uploaded on it does not work (a simple Blinky on pin 2 -Arduino pin, that is).

I hope the programmer is ok, it works on Attiny2313, so I think the usbasp is ok.

Is there any other way to test an Atmega168, other than upload the simplest sketch on it? It is not a big gap in the budget, but I want to know what caused the problem, in order to avoid it in the future.

Half of problem solved: I purchased my Atmega8 and it did not work with the boards file I posted earlier, so I had to set the board to Arduino NG/Atmega8 and upload the sketch by Upload by programmer option. It looks fine and it is a lot cheaper an Atmega168 that I initially purchased. i'll keep you posted.