ATtiny84 – Can't get analogRead() to work

I've just started working with the ATtiny84 chip and haven't had any issues accessing its digital pins with my sketches. However, I've been unable to figure out how to set up a pin for analogRead() in order to work with a TMP36 temperature sensor.

I've come across various suggestions, including adding this to setup():

  • DDRA &= ~(1 << PA2); // set pin A2 as input

as well as this post from the forum:

I also looked over the Analog Input Circuitry section starting on page 125 of the Atmel datasheet, but I don't have enough experience to grasp all of the details.

If someone could point me in the right direction for getting a proof-of-concept with the ATtiny84's analog read capabilities, that would be much appreciated.

I've attached a schematic of my circuit as well as my sketch. I'm using the Arduino IDE v1.8.19 with ATTinyCore.

const int analog_TMP36 = A2;  // physical pin 11

const int led_green = 7;      // physical pin 6
const int led_yellow = 8;     // physical pin 5
const int led_red = 9;        // physical pin 3

const float baselineTempF = 75.0;

  
void setup() {
  pinMode(analog_TMP36,       INPUT);
  
  pinMode(led_green,          OUTPUT);
  pinMode(led_yellow,         OUTPUT);
  pinMode(led_red,            OUTPUT);
  
  digitalWrite(led_green,     LOW);
  digitalWrite(led_yellow,    LOW);
  digitalWrite(led_red,       LOW);
}


void loop() {
  int TMP36_value = analogRead(analog_TMP36);
  
  float voltage = (TMP36_value / 1024.0) * 5.0;
  float tempC   = (voltage - 0.5) * 100.0;
  float tempF   = (tempC * 9.0 / 5.0) + 32.0;

  // if tempF between 75 and 85, only green LED on
  if ((tempF >= baselineTempF) && (tempF < (baselineTempF + 10.0))) { 
    digitalWrite(led_green,  HIGH);
    digitalWrite(led_yellow, LOW);
    digitalWrite(led_red,    LOW);

  // if tempF between 85 and 90, only yellow LED on
  } else if ((tempF >= baselineTempF + 10.0) && (tempF < (baselineTempF+15.0))) {
    digitalWrite(led_green,  LOW);
    digitalWrite(led_yellow, HIGH);
    digitalWrite(led_red,    LOW);

  // if tempF 90 or above only red LED on
  } else if (tempF >= baselineTempF+15.0) {
    digitalWrite(led_green,  LOW);
    digitalWrite(led_yellow, LOW);
    digitalWrite(led_red,    HIGH);

  // if tempF less than 75, all LEDs off
  } else {
    digitalWrite(led_green,  LOW);
    digitalWrite(led_yellow, LOW);
    digitalWrite(led_red,    LOW);
  }

  delay(3000);
}

Thanks in advance for any help.

  1. What core are you using?

  2. What version of that core are you using?

The correct answers to those questions are ATTinyCore, and 1.5.2 the latest released version if you want the best chance of things working. Do you have the builtin debug serial TX pin available (I don't remember it for the t84 off the top - or bottom - of my head) See the part ATTiny84 part specific documentation (note that the function to move the TX pin is broken in pre 2.0.0, and basic functionality is broken in 2.0.0 dev, so yo don't have any options for the TX pin, and you'll never have options for the RX pin, but you can disable the RX functionality with a one-liner in that part specific documentation; that way you could print out the values you're getting and see where things are going wrong. ) ATTinyCore 1.5.2 tiny x4 part specific reference - be sure to read the main readme too, and in that branch - because the readme in the 2.0.0-dev branch reflects oodles of changes that aren't in the release yet.

But you're most likely dealing with behavior inherited from the original attinycore, which I didn't have the wisdom at the time to realize was utterly moronic when I took over from the abandoned project. Analog and digital pin numbers are not the same thing, and yes, this is the dumbest thing since I don't even know what. There are two seperate and not necessarily well correlated sets of pin numbers for analogRead and everything else. ATTinyCore 1.5.2 or any earlier versions of attinycore I'm aware of behave that that. On ATTinyCore 2.0.0, you will be expected to call the digital pin number and hjave anal will work on ATTinyCore 2.0.x and is the reason that it's a "major version" (though it also adds a laundry list of features most of which are already implemented including something like 500 pre-built bootloader binaries to support different clock speeds and parts. By contrast on modern AVRs we got by with like 8 builds for the whole of megatinycore. When microchip took over, they took away the dartboards that Atmel used to pick the pinout. It should be released in a month - but I make no claims about which month that will be. It's planned release date is Q4 2021, so we're running a little behind schedule.

In short that is what it is most likely, still when i look at the pinout i found, you seem to have defined the correct pin nr.
So all that remains is a bit of trial and error, see if the current sketch works with pin 12 as an input would be my first try. Then i would try

const int analog_TMP36 = ADC2;  // physical pin 11

these are within the current sketch / wiring.
Then i would just use a potmeter, connect it across Vcc - GND with the variable output to an analog pin, while writing the result to a PWM output with a led on there. (maybe first make sure that the led works with PWM)

So what happens when you run your sketch?

Thanks for responding @DrAzzy . It's possible that I'm misunderstanding your two initial questions, but I have the following in the Arduino IDE's 'Additional Boards Manager URLs' dialog (after other URLs for working with ESP boards):

It appears that the JSON contains multiple versions of ATTinyCore – and I see version 1.5.2 listed as one of them – but I don't know how to specify that particular version to use within the Arduino IDE.

Here's a screenshot of how I have it configured, if it's helpful:

Also, I need to look into this bit when I have some time to parse it out:

You can disable the RX functionality with a one-liner in that part specific documentation; that way you could print out the values you're getting and see where things are going wrong.

Thanks again, and I look forward to ATTinyCore 2.0.0, whenever it's released :+1:

Thanks for responding @Deva_Rishi . Not sure if you meant to replace A2 with ADC2 in your comment, but the compiler responded with 'ADC2' was not declared in this scope:

const int analog_TMP36 = ADC2; // physical pin 11

Also, changing this to:

const int analog_TMP36 = A1; // physical pin 12

and wiring the TMP36's output to the the ATtiny84's pin 12 made no difference.

Thank you for the suggestions.

Hey @killzone_kid. Unfortunately nothing appears to happen when I upload the sketch to the ATtiny84, move the chip over to the circuit, and power it up with 5V from my bench supply.

I've attached a short video of what I expect to happen; first showing how the circuit works using an Uno, then moving the TMP36 over to the circuit with the ATtiny84 with the same sketch and wiring/pin configuration as the Uno:

Uno_and_ATtiny84_analog_test-2 copy

Thanks for your interest.

do you know if the sketch even runs? Id start with something very simple, loop where it reads value of ADC pin and sends it to PWM pin which has LED. Run it, touch ADC pin, connect it to ground, connect it to VDD, see if LED behaves accordingly. Also how do you program your ATTiny, what clock setting?

Can you confirm it works using a simple blink sketch ?

Because i wonder about that as well.

Well it is the latest version, if you have clicked 'install' that is the one it would select by default.
It also shows you which version is installed in the board manager.

I would do the pinout clockwise, but for the ADC pins it doesn't matter really i think.

So I don't have a comprehensive answer to how I ultimately got this to work, but for anyone who stumbles across this post who just needs to get an ATtiny84 to do the following using an Uno as the chip programmer to:

  1. Read an analog signal
  2. Verify it's working by outputting to a PWM pin

Here's what I did.

Pre-requisities:

  • The ArduinoISP example sketch has been uploaded to the Uno (Arduino IDE → File → Examples → ArduinoISP)
  • The ATtiny board description is included in the Arduino IDE's Additional Boards Manager (http://drazzy.com/package_drazzy.com_index.json) (Arduino IDE → Preferences)
  • The programmer has been configured (Arduino IDE → Tools) resembling the screenshot I posted earlier, including Counterclockwise pin mapping
  • The Uno is powered up and the correct port is set in the IDE

Components:

  • 1KΩ potentiometer
  • LED
  • 220Ω resistor
  • ATtiny84 (duh)

Step 1. Upload this sketch to the ATtiny84 via the Uno (for whatever reason, I have to always re-burn the bootloader each time I upload a new sketch. Not sure if this is typical, but it seems to work for me):

int potPin = A1;  // physical pin 12
int ledPin = 2;   // physical pin 5 (PWM-enabled)
int potVal = 0;

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  potVal = analogRead(potPin);
  int potValMapped = map(potVal, 0, 1023, 0, 255);
  analogWrite(ledPin, potValMapped);
  delay(10);
}

Step 2: Power off the Uno and move the ATtiny84 to the breadboard you'll be wiring up the components to.

Breadboard / Wiring (this describes the connections in a clockwise fashion, starting at the chip's top-left pin):

  • Physical pin 1 → 5V
  • Physical pin 5 → LED anode [+]
  • Physical pin 12 → Potentiometer, center pin
  • Physical pin 14 → GND

Additionally:

  • Connect the LED cathode to GND via the 220Ω resistor
  • Connect the potentiometer's remaining 2 pins to 5V and GND (polarity not a big deal here)

Step 3: Power up the circuit with 5V.

If all went according to plan, you should be able to control the duty cycle of the LED on physical pin 5 which is PWM-enabled with the voltage divider output coming from the analog potentiometer on physical pin 12.

Seems simple, but it took me all week to figure it out :wink: Hope someone finds this helpful.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.