Code works on Uno but not on ATtiny85

This code works perfectly on my Arduino Uno, using Pin A0 for the signal input and Digital Pin 1 for the LED. However, after burning the code to my ATtiny84, the LED stays on constantly, regardless of the signal present at the signal pin—it remains high at all times. Is this code not compatible with the ATtiny84?

const int signalPin = 2; // The analog pin reading the DC signal
const int ledPin = 1;     // The digital pin controlling the LED
const int threshold = 11; // -23 dBu
const unsigned long holdTime = 2000; // Time in milliseconds to hold LED on

unsigned long ledTurnOnTime = 0; // To track when the LED was turned on
bool ledOn = false; // To track the LED state

// Define unused pins
const int ncPin2 = 0; // Not connected
const int ncPin3 = 3; // Not connected
const int ncPin4 = 4; // Not connected

void setup() {
  pinMode(ledPin, OUTPUT);  // Set LED pin as an output
  pinMode(signalPin, INPUT); // Set signal pin as input

  // Set unused pins to input pull-up mode
  pinMode(ncPin2, INPUT_PULLUP);
  pinMode(ncPin3, INPUT_PULLUP);
  pinMode(ncPin4, INPUT_PULLUP);
}

void loop() {
  int signalValue = analogRead(signalPin); // Read the analog signal

  // If signal is above threshold, turn on LED and record the time
  if (signalValue >= threshold) {
    digitalWrite(ledPin, HIGH);   // Turn on the LED
    ledTurnOnTime = millis();     // Record the time the LED was turned on
    ledOn = true;                 // Set flag to indicate LED is on
  }

  // Check if the LED is on and if 2 seconds have passed since it was turned on
  if (ledOn && (millis() - ledTurnOnTime >= holdTime)) {
    digitalWrite(ledPin, LOW);    // Turn off the LED
    ledOn = false;                // Reset flag
  }
}

Verify pins. I do not understand the official datasheet, but my notes show "D1" on pin 3 and "A0" on pin 13, named "alternative pinout" (I do not know why) on a few bits of information, but I had a hard time settling on those values.

1 Like

1. Are you using ATTinyCore which has defined/mapped the IO pins of ATtiny84 into Ardduino compatiable DPins? The IO pin mappings are as follows:

PPin  Signal Name  Arduino DPin
13    PA0/ADC0     0
12    PA1/ADC1     1
11    PA2/ADC2     2
10    PA3/ADC3     3
9     PA4/ADC4     4
8     PA5/ADC5     5
7     PA6/ADC6     6
6     PA7/ADC7     7

2     PB0          10
3     PB1          9
5     PB2/INT0     8
4     RST/(PB3)    11
1     VCC
14    GND

2. Are you using Arduino as ISP Programmer?
3. Are you using fresh ATtiny84 chip?
4. Is that sketch of post #1 for stand-alone ATtiny84?

In what way you want the LED at DPin-1 of UNO to behave when input DC signal at A0-pin slowly changes?

1 Like

Something odd jumped out at me.

You say you're using an ATTiny84. That's a 14 pin DIP IC, with as many as 11 I/Os.

In your sketch, you make sure to set unused pins to INPUT_PULLUP. But only 3 of them: 0, 3 and 4. You use 1 for the LED and 2 for the ADC input. You leave 5-8 (or 5-10 if you're not using an external crystal) alone.

That's only 5 I/Os out of 9 (or 11) that get set up. Coincidentally, 5 is the number of I/O pins on an ATTiny85; an 8 pin DIP IC.

Before I delve any deeper into this, can you confirm that you are using the ATTiny84, the 14 pin IC, and not the ATTiny85, the 8 pin IC?

1 Like

Hi, thanks for the response! That was a typo—I'm actually using the 8-pin ATtiny85 chip.

When testing the code and functions, I’m using an Uno. For burning, I’m using a Nano as the ISP.

In the Tools menu, I select:

  • Board: "ATtiny45/85 (Optiboot)"
  • Chip: "ATtiny85"

I burn the bootloader first, then upload the code. I’m using a fresh ATtiny85 chip, and I’ve tried multiple ones to rule out any issues.

This could be the issue—I may have forgotten to select "Arduino as ISP" under the Tools menu before I uploaded the code. I’ll check when I’m back at the computer in two hours. Thanks!!

Its been a long time but when I last used the ATiny84A (pdip package) I used this code:
Warning, I like to control the device at the register level as it helps me understand how to best use the processor.

You can also see if there are examples in the IDE (Files/example .......)

/*
ADC Test with results printed to PB1
ADC = PA1
Print out = PB1

v2 - works with ADC, SoftSerial, Average time and map

*/

#include <SendOnlySoftwareSerial.h>

uint16_t onTime;
const unsigned int minonTime   =    1;       // counts
const unsigned int maxonTime   =    50;  

SendOnlySoftwareSerial mySerial(PIN_PB1);

void setup()
{
  
  DDRA = 0b00000000; //bit(PA0) | bit(PA2) | bit(PA3) | bit(PA4) | bit(PA5) | bit(PA6);  // PA7 is an input
  DDRB = 0b00000010;
  

  mySerial.begin(9600);
  initADC();

  mySerial.println("starting...");
}

int i;

void loop()
{
    //Read pot and print..
  
    uint16_t PulseTime;
    uint16_t ADCsum = 0;
    uint8_t i = 0;

    for(i=0;i<6;++i){
        ADCSRA |= (1 << ADSC);         // start ADC measurement
        while (ADCSRA & (1 << ADSC) ); // wait till conversion complete 
        ADCsum += ADCH;
    }
    
    uint16_t OnTime = ADCsum/6;
    
  PulseTime = map(OnTime, 0, 255, maxonTime, minonTime);
  mySerial.print ("OnTime:   ");
  mySerial.print (OnTime);
  mySerial.print ("    PulseTime:   ");
  mySerial.println (PulseTime);
  
  delay (1000);
}


void initADC()
{
    // enable the ADC input pin(s), here we pick PA1.
   ADMUX =
            (0 << REFS1) |     // Sets ref. voltage to Vcc, bit 1   
            (0 << REFS0) |     // Sets ref. voltage to Vcc, bit 0
            (0 << MUX5)  |     // use ADC1 for input (PA1), MUX bit 5
            (0 << MUX4)  |     // use ADC1 for input (PA1), MUX bit 4
            (0 << MUX3)  |     // use ADC1 for input (PA1), MUX bit 3
            (1 << MUX2)  |     // use ADC1 for input (PA1), MUX bit 2
            (1 << MUX1)  |     // use ADC1 for input (PA1), MUX bit 1
            (1 << MUX0);       // use ADC1 for input (PA1), MUX bit 0

  ADCSRA = 
            (1 << ADEN)  |     // Enable ADC 
            (1 << ADPS2) |     // set prescaler to 16, bit 2 
            (0 << ADPS1) |     // set prescaler to 16, bit 1 
            (0 << ADPS0);      // set prescaler to 16, bit 0 
			
  ADCSRB = 
            (1 << ADLAR);      // left shift result (for 8-bit values)
	//        (0 << ADLAR);      // right shift result (for 10-bit values)
}

A couple of things:

  1. The ATTinyCore needs you to use A1 for analogRead, not 2: if you look in pins_arduino.h for the ATTiny85, you'll see that A1 is defined as 0x80 | 1. So change const int signalPin = 2; to const int signalPin = A1;
  2. Your comments are inconsistent. If you want the LED to go out 2 seconds after being turned on, you need to change
if (signalValue >= threshold) {

to

if (!ledOn && signalValue >= threshold) {

The way you have it now, the LED goes off 2 seconds after the signal goes below the threshold. That may be what you want, but "Check if the LED is on and if 2 seconds have passed since it was turned on" isn't the same thing as "Check if the LED is on and if 2 seconds have passed since they signal went below the threshold" .

You may follow the procudures of the attached file to program ATtiny85 MCU.
ProgrammingATtiny85.pdf (242.4 KB)

And please, edit the title of your thread.

1 Like

Thanks for the pdf file. Very good

Thanks, everyone, for your help! The issue turned out to be the pin name in the code. Using "A1" instead of just 2 made everything work as expected. I’ve now successfully uploaded the code to my ATtiny85. This was my first time using the analog pins—I had only used the two digital pins before and just labeled them "0" and "1." Now I understand the importance of the "A" prefix and the distinction between digital and analog pins.

Yes the description was a little bit wrong. What I ment was that the led should stay on for 2 seconds after the signal goes below the threshold. Thanks

Final working code:

const int signalPin = A1; // The analog pin reading the DC signal
const int ledPin = 1;     // The digital pin controlling the LED
const int threshold = 11; // -23 dBu
const unsigned long holdTime = 2000; // Time in milliseconds to hold LED on

unsigned long ledTurnOnTime = 0; // To track when the LED was turned on
bool ledOn = false; // To track the LED state

// Define unused pins
const int ncPin0 = 0; // Not connected
const int ncPin3 = 3; // Not connected
const int ncPin4 = 4; // Not connected

void setup() {
  pinMode(ledPin, OUTPUT);  // Set LED pin as an output
  pinMode(signalPin, INPUT); // Set signal pin as input

  // Set unused pins to input pull-up mode
  pinMode(ncPin0, INPUT_PULLUP);
  pinMode(ncPin3, INPUT_PULLUP);
  pinMode(ncPin4, INPUT_PULLUP);
}

void loop() {
  int signalValue = analogRead(signalPin); // Read the analog signal

  // If signal is above threshold, turn on LED and record the time
  if (signalValue >= threshold) {
    digitalWrite(ledPin, HIGH);   // Turn on the LED
    ledTurnOnTime = millis();     // Record the time the LED was turned on
    ledOn = true;                 // Set flag to indicate LED is on
  }

  // Check LED and stay on for 2 seconds after the signal goes below the threshold
  if (ledOn && (millis() - ledTurnOnTime >= holdTime)) {
    digitalWrite(ledPin, LOW);    // Turn off the LED
    ledOn = false;                // Reset flag
  }
}

According to data sheets, the actuula signal name is ADC1 attached with physical pin (PPin) of ATtuny85.

Where have you found the definition of A1 for the ADC1 signal atached with PPin-7?

Also, where have you found the definition of 2 (DPin-2) for the alternate digital IO signal attached with PPin-7?

Chat GPT

ChatGPT can ony be trusted if it matches with what has been defined in the ATTinyCore Package.