Giter Site home page Giter Site logo

analogcomp's Introduction

******** analogComp.h  *******

analogComp

This little library can be used to set and manage the analog
comparator that is integrated in a wide variety of
Atmel microcontrollers

Written by Leonardo Miliani <www DOT leonardomiliani DOT com>


***********************
Version history

v. 1.2.4: fixed code to enable/disable digital buffers (they were inverted!) - thanks to ami2go. Fixed ADC enable/disable: for a type, the code worked on the wrong register
v. 1.2.3:  added support for ATmega32U4 (old Leonardo boards) - thanks to stefandz
v. 1.2.2:  added compatibility with Arduino IDE >= 1.6.7
v. 1.2.1:  fixed a bug that let the ADC off after a comparison
v. 1.2.0:  fixed a bug into the conversion from analog to phisical pins
v. 1.1.1:  now it calls the correct interrupt vector for the MCU in use
v. 1.1.0:  fixed several issues with ATtinyx313 and ATtinyx5
v. 1.0.1:  fixed Atmega8/A support
v. 1.0.0:  new methods and bug fixing
v. 0.1.0:  the library can enable/disable an interrupt on AC
v. 0.0.1:  early release - prototype of the library


***********************
How to use it - Methods

Unpack the library and copy it into your /libraries folder, that usually
is in your sketchs' folder. Then include the library by adding the
following code at the top of your sketch:

#include "analogComp.h"


Now you can set what has to be connected to the inverting (AIN-) and
non-inverting (AIN+) inputs of the analog comparator. Usually, the
AIN+ is connected to external pin AIN0 and the AIN- is connected to
external pin AIN1. The AIN+ can be connected to the internal voltage
reference (usually 1V1), while the AIN- can be connected to any of the
analog input pins of the microcontroller. (see "Supported Microcontrollers"
for specific limitations)


To choose the analog comparator inputs use the method setOn():

analogComparator.setOn([AIN+, AIN-]);

For the AIN+ you can choose between the following:
AIN0: set the AIN0 pin as input
INTERNAL_REFERENCE: set the internal voltage reference as input

For the AIN- you can choose between the following:
AIN1: set the AIN1 pin as input
A0..Ax: set the Analog Input Channel (max number depends of the MCU)

AIN+ and AIN- are optionals, if not set, AIN0 and AIN1 will be used.

You can enable an interrupt routine to be executed when an event occurs:

analogComparator.enableInterrupt(myFunction[, event]);

myFunction is the name of the function to be called when the event
occurs. event can be:
CHANGE: when the comparation changes between AIN+>AIN- and AIN+<AIN-
RISING: when the voltage on AIN+ becomes greater than the voltage on AIN-
FALLING: when AIN+ becomes smaller than AIN-
event is optional, if not set CHANGE will be choosen.


You can disable the interrupt by calling this method:

analogComparator.disableInterrupt();


You can wait for a comparation to occur:

analogComparator.waitComp([timeout]);

timeout is optional and rapresents the number of milliseconds to wait
before to return (default is 5000).
This method will return false (0) if voltage on AIN- will remain
greater than the voltage on AIN+ for the whole interval specified by
timeout; it will return true (1) if AIN+ will become greater than
AIN- during the interval.

If the analog comparator won't be set up before to call the waitComp
method, by default the library will use AIN0 and AIN1 pins.


To switch off the analog comparator, call this method:

analogComparator.setOff();

It will switch off the analog comparator and will disable any enabled
interrupt.


***********************
How it works

The Analog Comparator is an operational amplifier (op-amp) integrated
into the microcontroller. An op-amp has 2 inputs: a non-inverting input,
AIN+, and an inverting input, AIN-. When the voltage that is present on
the non-inverting input is greater than the voltage that is present on
the inverting input, the op-amp will set to high its output. The signal
can be used to raise an interrupt to do an automatic operation.
Different combinations of inverting and non-inverting inputs can be
selected by manipulating the internal registers.


***********************
Supported microcontrollers

Actually the library works with a wide variety of Atmel microcontrollers
and Arduino boards:
- Attiny2313/4313 [1]
- Attiny24/44/84
- Attiny25/45/85
- Atmega344/644/1284
- Atmega8
- Atmega48/88/168/328 [3] (Arduino UNO)
- Atmega640/1280/1281/2560/2561 (Arduino MEGA)
- Atmega32U4 [2] (Arduino Leonardo/Micro)

Specific limitations:
[1] Attiny2313/4313:
due to the fact that these MCUs don't have an integrated ADC, only AIN1
is allowed for AIN-.

[2] Atmega32U4:
don't use analog input lines A2 & A3 because they are not phisically connected
to external pins on Leonardo & Micro boards

[3] Atmegax8:
some SMD versions of this chip have 2 extra analog input pins; so, to be able to use
them inside the library, please edit the analogComp.h file and change the value from
6 to 8 of the following compiler's directive:
#define ATMEGAx8
#define NUM_ANALOG_INPUTS 6

***********************
Licence

This library is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3.0 of the License, or (at your
option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


***********************
Document revision

Last revision: 2018/04/03

analogcomp's People

Contributors

leomil72 avatar stefandz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

analogcomp's Issues

Atmega 32u4 analogRead doesn't work after setOn/setOff

Atmega 32u4 with Arduino Leonardo bootloader. Arduino IDE v1.8.1, win 10.
Current version: 1.2.2 - 2016/02/20
//library version #define ANALOGCOMP_VERSION 123
same with library version 1.2.2 from leonardomiliani.com

analogRead() works as intended, but after pair of analogComparator.setOn() and analogComparator.setOff() it just repeats first readed value.

Minimum example to reproduse:
sketch_mar21a.ino.txt

Changing row 253 in analogComp.cpp:
AC_REGISTER |= (1<<ADEN); //ACDSRA = oldADCSRA; to
AC_REGISTER |= (1<<ADEN);
ADCSRA = oldADCSRA;
helps to restore analogRead() functionality.

Library handles ATMega 2560 etc. wrong!

Hi leomil72,

I tested your lib and noticed, that you handle ATMEGA 2560 (16 analog ins) wrong.

If you select A0 to A15 for AIN+ with "SetOn" it only works for A0..A7.
You must only use Bit0..Bit2 of ADMUX in case of using A/D-multiplexer for analog comparator.
Bit 3 has to be written to ADCSRB's MUX5-Bit to complete the 4 bits necessary for value 0..15.

in addition, the Manual says, that you have to clear PRADC-Bit in PRR0 to use A/D-Multiplexer for comparator.

I entered the following in analogComp.cpp to correct: (from line 109 in analogComp.cpp)

#ifndef ATMEGAxU
            #ifdef ATMEGAx0
              //Bit "PRADC" in Register “PRR0" (Power Reduction Register 0)” has to be cleared, to use input multiplexer of A/D for comparator.
              PRR0 &= ~(1<<PRADC);
              ADMUX |= ((tempAIN1)& 0b00000111);    //only MUX2 .. MUX0 are used for selection
              AC_REGISTER &= ( ~(1<<MUX5));         //Bit4 must be written to AC_REGISTER (ADCSRB for ATMEGA2560) 
              AC_REGISTER |= ((tempAIN1 >7)<<MUX5);
            #else
              ADMUX |= tempAIN1;  //choose the ADC channel (0..NUM_ANALOG_INPUTS-1)
            #endif

analog comparator interrupts trigger shifting/not stable

hello,

I'm trying to use orangkucing's teensy3 fork on a teensy3.5, IDE1.8.7, win10

I eventually got it running, but interrupts are really all over the place.
Since I cannot open issues on his fork and considering that the core of the work is yours, I thought I'd open an issue here, hope it's OK.

Now, to clarify, I'm trying the analogComp_enableInterrupt.ino with:

Testing the first analog comparator CMP0 with:
AIN- coming from a pot I had lying around (+ 3V3, - AGND, output to CMP0_IN0-pin13, or more conventiently CMP0_IN2-pin35 A16)
AIN+ from the relevant DAC1_OUT-pin67 aka A22 which for the test I drive at #700 using 10bit resolution

Testing it turning the pot left and right and looking for when the led lits, it was obvious that something was wrong. LED was flashing at different points in the pot, looked like it shifted back and forth, so I just added a Serial.println to check the values of AIN1 and AIN0 when it triggers.

AIN1: 182, AIN0: 700 AIN1: 264, AIN0: 701 AIN1: 193, AIN0: 701 AIN1: 221, AIN0: 701 AIN1: 165, AIN0: 701 AIN1: 271, AIN0: 701 AIN1: 164, AIN0: 701 AIN1: 300, AIN0: 701 AIN1: 188, AIN0: 701 AIN1: 206, AIN0: 701 AIN1: 180, AIN0: 701 AIN1: 228, AIN0: 701 AIN1: 219, AIN0: 701 AIN1: 216, AIN0: 701 AIN1: 126, AIN0: 701 AIN1: 258, AIN0: 701 AIN1: 169, AIN0: 700 AIN1: 255, AIN0: 701 AIN1: 192, AIN0: 700 AIN1: 211, AIN0: 701 AIN1: 113, AIN0: 700

Lower values is when I was turning the pot down and higher when up, so seems to be a delay which I could possibly accept. BUT I do get some values jumping a bit more, see most are around 180-220 and occasionally a 271 and 300 a 258 etc.
System has to accurately monitor and stop a shaft rotating (via digital signals to two DD relays operating solenoids that control 100bar of hydraulic pressure rams going back and forth), I cannot afford more than 3-5 off (should convert to less than a degree rotation)

Actually and that's my second problem, I see the system triggering at values generally shifted from the AIN+ of 700 (approx 2.26V) as it AIN- is at around 200 (way under 1V!) Any idea why 2.26V reference get triggered with anything form 0.6V- 0.8V?

The code I'm using is simply yours with an extra debug print line:

`//include the library
#include "analogComp.h"

//global variables
const byte LED13 = 13; //set the output LED
boolean enableLed = false; //used to check if the interrupt has raised

//let's set up the hardware
void setup() {
pinMode(LED13, OUTPUT); //LED pin as output
pinMode(A22, OUTPUT); //the PORT DAC output set to a value...
analogWriteResolution(10); //10bit 1023 max
analogWrite(A22, 700);
//non inverting AIN+ = AIN0 = internal voltage reference
//inverting AIN- = AIN1 = analog input
analogComparator.setOn(AIN0, A22); //we instruct the lib to use voltages on the pins
analogComparator.enableInterrupt(changeStatus, CHANGE); //FALLING RISING CHANGE we set the interrupt and when it has to be raised
}

//main loop
void loop() {
if (enableLed) { //let's check if the analog comparator has raised the interrupt
Serial.println("AIN1: " + String(analogRead(A16)) + ", AIN0: " + String(analogRead(A22)));
//yes, so we do a little blink of the LED
digitalWrite(LED13, HIGH);
delay(50);
digitalWrite(LED13, LOW);
enableLed = false;
}
}

//interrupt to be raised by the analog comparator
void changeStatus() {
enableLed = true; //let's inform the main loop that the condition has been reached by the analog comparator
}`

Possible issues:

  1. COMP0 not happy to use an internally voltage reference (DAC1_OUT) although on all documentation I read it's meant to be acceptable solution.
  2. internal voltage not stable, well checked it with a half decent digital v/meter and it's stuck to 2.27V doesn't move
  3. current issues, unlikely as I drive the teensy from a stabilised 5A 5V supply and not the USB cable (chopped red out of the usb)

I wonder if you have any idea on what I'm doing wrong. I've spent a couple of days trying to get it running as I initially was wiring it all wrong (assumed pin11 to be A11 and was using DAC0 for CMP0 whereas it should be DAC1) and now that's running the results are rather disappointing.

BTW, I have the full system already running with a while loop for each shaft (got two to work with) BUT I need the processor to do other stuff as well and cannot afford the waiting. There's a MPC9250 sensor that needs to be polled all the time and mins and maxs of roll and accel recorded for further actions.
So it's either going to be teensy3 with interrupts or ESP32 with dual threading running both in parallel...

cheers

Vassilis

Pro Micro, AIN0/D7 OK but can't relate any other pin with the analog comparator (lib 1.2.4, Arduino IDE 1.8.9)

analogComp library ver 1.2.4
Arduino IDE ver 1.8.9

I can't have the library work on a Pro Micro which is apparently identical to this one (except it is blue/green): https://www.sparkfun.com/products/12640

The pinout scheme is among the links in the Documents tab:
https://cdn.sparkfun.com/datasheets/Dev/Arduino/Boards/ProMicro16MHzv1.pdf

I can trigger the interrupt through pin AIN0, D7, but I haven't managed to get any reaction from any other pin with any combination of 0 / 3.3 / 5 Volt.

I've been going through web pages like the following ones

but I haven't been able to figure out a successful tweak yet.

Basically, I have been using the sketch coming with the lib except trying the setOn method on different pins and using pin 17 for the builtin LED.

#define __ENABLE_SERIAL__ANALOG_COMP__
#define __CHECK_COMPILE_TIME_FLAGS__
// #define __TRY_THE_ATMEL_STUDIO_EXAMPLE__
/*
This is a simple sketch to demonstrate the use of analogComp, a
library to manage the analog comparator included in a wide 
variety of Atmel microcontrollers

This sketch enables an interrupt to be raised when on the analog input 0
(pin AIN0) there is a voltage greater than the voltage on the
analog input 1 (pin AIN1). To test the sketch, build the following
circuit:
- connect pin AIN1 to pin 3V3
- connect pin AIN0 to GND using a pull-down resistor (10Kohm or greater)
- connect pin AIN0 to pin 5V to activate the interrupt


More info on the analog comparator can be found reading the datasheet.

Please read the README file to know how to use this library.

Written by Leonardo Miliani <leonardo AT leonardomiliani DOT com>
	
This code and the analogComp library are free software; you can redistribute 
and/or modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3.0 of the License,
or (at your option) any later version.

This work is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

*/

// #ifndef ARDUINO_AVR_PROMICRO
//include the library
#include "analogComp.h"
// #endif


//global variables

#ifdef __ENABLE_SERIAL__ANALOG_COMP__
long count, columnsCount;
#endif

#ifdef ARDUINO_AVR_PROMICRO
#define BUILTIN_LED_PIN 17 //set the output LED
#else
#define BUILTIN_LED_PIN 13 //set the output LED
#endif

volatile boolean enableLed = false; //used to check if the interrupt has raised



//let's set up the hardware
void setup() {
    pinMode(BUILTIN_LED_PIN, OUTPUT); //LED pin as output
#ifdef ARDUINO_AVR_PROMICRO

#ifdef __TRY_THE_ATMEL_STUDIO_EXAMPLE__
    // https://www.electronicwings.com/avr-atmega/atmega1632-analog-comparator
    // DDRC |= 0x80;    /* Make pin 7 of PORTC as output */
    ADCSRA &= (1<<ADEN);  /* Disable ADC */
    ADMUX = 0x00;   /* Select ADC0 as a -ve pin of comparator */
    SFIOR |= (1<<ACME); /* Enable analog comparator */
    // ^ error 'SFIOR' was not declared in this scope. That example is for Atmel Studio.
#else
    analogComparator.setOn(7, A10); //we instruct the lib to use voltages on the pins
#endif

#else
    analogComparator.setOn(AIN0, AIN1); //we instruct the lib to use voltages on the pins
#endif

    analogComparator.enableInterrupt(changeStatus, CHANGE); //we set the interrupt and when it has to be raised

    count = 0;
    columnsCount = 0;
}

//main loop
void loop() {
    if (enableLed) { //let's check if the analog comparator has raised the interrupt
        //yes, so we do a little blink of the LED
        digitalWrite(BUILTIN_LED_PIN, HIGH);
#ifdef __ENABLE_SERIAL__ANALOG_COMP__
        Serial.println("*** IRQ TRIGGERED ***");
#endif
        delay(200);
        digitalWrite(BUILTIN_LED_PIN, LOW);
        enableLed = false;
    }
#ifdef __ENABLE_SERIAL__ANALOG_COMP__
    else {
      if (++count == 10000) {
        count = 0;
        Serial.print("-");
        if (++columnsCount == 80) {
          columnsCount = 0;
          Serial.println("");

#ifdef __CHECK_COMPILE_TIME_FLAGS__
#ifdef __AVR_ATmega32U4__
          Serial.println("__AVR_ATmega32U4__ is defined");
#endif
#ifdef ATMEGAxU
          Serial.println("ATMEGAxU is defined (the analogComp lib does it, if __AVR_ATmega32U4__ is defined");
          Serial.println("Notice that this info could be printed out at compile time with compiler directives.");
          Serial.println("");
          Serial.print("AIN0 == "); // result 0
          Serial.print(AIN0);
          Serial.print("  -  AIN1 == "); // result 255
          Serial.println(AIN1);
          Serial.println("");
#endif
#endif
        }
      }
    }
#endif
}

//interrupt to be raised by the analog comparator
void changeStatus() {
    enableLed = true; //let's inform the main loop that the condition has been reached by the analog comparator
}

I'd be happy to test any suggested changes to the library (possibly subordinated to #ifdef ARDUINO_AVR_PROMICRO ... #endif if not of general validity).


Marginally, I get this warning (IDE 1.8.9):

/home/lemon/MANINST/arduino-1.8.9/portable/sketchbook/libraries/analogComp/analogComp.cpp: In member function 'uint8_t analogComp::setOn(uint8_t, uint8_t)':
/home/lemon/MANINST/arduino-1.8.9/portable/sketchbook/libraries/analogComp/analogComp.cpp:100:19: warning: comparison is always true due to limited range of data type [-Wtype-limits]
     if ((tempAIN1 >= 0) && (tempAIN1 < NUM_ANALOG_INPUTS)) { //set the AC Multiplexed Input using an analog input pin
                   ^

[MICRO] INTERNAL_REFERENCE on negative input not implemented.

analogComp.cpp file, line 35 states: "//for Atmega32U4, only ADMUX is allowed as input for AIN-"

But that seems not true, as ATmega32U4 datasheet, section 23.2 "Analog Comparator Multiplexed Input"(p.295) states: "If ACME is cleared or ADEN is set, the Bandgap reference is applied
to the negative input to the Analog Comparator."

disable digital buffer on pins AIN0 && AIN1 to reduce current consumption

Hello. Not a big issue. Library works well thank you for your work!
I was looking thought code and didn't undestand how one things works.
May be i didn't understand just you code.
Look at section of DIDR0 register (digital input disable)

#if defined(ATTINYx5)
	DIDR0 &= ~((1<<AIN1D) | (1<<AIN0D));
#elif defined(ATTINYx4)
	DIDR0 &= ~((1<<ADC2D) | (1<<ADC1D));
#elif defined (ATMEGAx4)
	DIDR1 &= ~(1<<AIN0D);
#elif defined (ATTINYx313)
	DIDR &= ~((1<<AIN1D) | (1<<AIN0D));
#elif defined (ATMEGAx8) || defined(ATMEGAx4) || defined(ATMEGAx0)
    DIDR1 &= ~((1<<AIN1D) | (1<<AIN0D));
#endif

It looks like you writing "0" while datasheets says it have to be "1" (Attiny24 page 117)

When this bit is written logical one, the digital input buffer on the AIN1/0 pin is disabled. The corresponding PIN register bit will always read as zero when this bit is set. When an analog signal is applied to the AIN1/0 pin and the digital input from this pin is not needed, this bit should be written logical one to reduce power consumption in the digital input buffer.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.