Attiny10 Sample code to analog read

I am looking for sample code for ATTINY 10 where i could Read analog pin and turn and turn of led.

I am using 20k pot value . is there way we can get count value like UART. Bitduino wont support it.

Here is sample code . initially trying Ledblink code which is working.

#include <avr/io.h>
#include <util/delay.h>

#define F_CPU 1000000UL // Define CPU frequency as 1MHz

void InitIO() {
  DDRB |= (1 << PB2); // Set PB2 as output (Relay)
}

void RelayOn() {
  PORTB |= (1 << PB2); // Set PB2 (Relay on)
}

void RelayOff() {
  PORTB &= ~(1 << PB2); // Clear PB2 (Relay off)
}

void DelayTime(uint32_t time_ms) {
  while (time_ms >= 1000) {
    _delay_ms(1000); // Delay for 1000 milliseconds
    time_ms -= 1000;
  }
  while (time_ms > 0) {
    _delay_ms(1); // Delay for remaining milliseconds
    time_ms--;
  }
}

int main() {
  InitIO();
  while (1) {
    RelayOn();
    DelayTime(20); // Delay for 20 milliseconds
    RelayOff();
    DelayTime(20); // Delay for 20 milliseconds
  }

  return 0;
}

Now i want PB0 to decide on-time and PB1 to decide Off time using analog pin.
PB2 used to Relayoutput. Pb3 i want use as digital input . If Digtial input is high Blink LED With on and off time got from Analog pin. If Digtial pin is LOW . keep relay always off. Currently facing issue with digital read and also analog pin.

#define F_CPU 1000000UL // Define CPU frequency as 1MHz
#include <avr/io.h>
#include <util/delay.h>

// ADC channel definitions
#define POT_CHANNEL 0 // PB0

void InitADC(uint8_t channel) {
	ADMUX = channel;
	if (channel == 0) {
		DIDR0 = (1 << ADC0D);
		} else if (channel == 1) {
		DIDR0 = (1 << ADC1D);
	}
	ADCSRA = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0);
}



uint16_t ReadADC(uint8_t channel) {

	ADMUX = (ADMUX & 0xF0) | (channel & 0x0F);
	ADCSRA |= (1 << ADSC);
	while (ADCSRA & (1 << ADSC));
	uint16_t adcResult = ADCL;
	return adcResult;
}

void InitIO() {
	DIDR0 = (1 << ADC0D); // Disable digital input buffer for PB0
	DDRB |= (1 << PB2); // Set PB2 as output (Relay)
}

void RelayOn() {
	PORTB |= (1 << PB2); // Set PB2 (Relay on)
}

void RelayOff() {
	PORTB &= ~(1 << PB2); // Clear PB2 (Relay off)
}

void DelayTime(uint32_t time_ms) {
	while (time_ms >= 1000) {
		_delay_ms(1000); // Delay for 1000 milliseconds
		time_ms -= 1000;
	}
	while (time_ms > 0) {
		_delay_ms(1); // Delay for remaining milliseconds
		time_ms--;
	}
}

int main() {
	InitIO();
	InitADC(POT_CHANNEL);

	while (1) {
		uint16_t potValue = ReadADC(POT_CHANNEL);
		uint8_t range = (uint8_t)(potValue / 102); // Map 10-bit ADC value to 10 ranges (0-9)

		uint32_t timeValues[10] = {1000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, 100000}; // 1s to 100s
		uint32_t timeValue = timeValues[range];

		 DelayTime(timeValue); // Wait for the specified delay
		 RelayOn(); // Turn the relay on after the delay
				 while (1) {
					 // Keep the relay on indefinitely
				 }
		}

	return 0;
}



It might be easier to incorporate the IDE and all it brings to the party

2 Likes

Here is code for analog read value and blink led. some extent is working . but i cant tune the count value

#include <avr/io.h>
#include <util/delay.h>

#define F_CPU 1000000UL

void InitIO();
void RelayOn();
void RelayOff();
void RelayToggle();
void DelayTime(uint16_t delay_ms);
uint16_t ReadAnalogPin(uint8_t pin);

int main() {
    InitIO();
    
    while (1) {
        // Read the analog value from PB1 (ADC1)
        uint16_t adcValue = ReadAnalogPin(1); // PB1 is ADC1
        
        // Determine delay based on ADC value
        uint16_t delayTime;
        if (adcValue < 256) {
            delayTime = 1000; // 1 second
        } else if (adcValue < 512) {
            delayTime = 3000; // 3 seconds
        } else if (adcValue < 768) {
            delayTime = 5000; // 5 seconds
        } else {
            delayTime = 10000; // 10 seconds
        }
        
        // Toggle the relay or LED connected to PB2
        RelayToggle();
        DelayTime(delayTime);
    }
    
    return 0;
}

void InitIO() {
    // Set PB2 as output, PB0 and PB1 as input (analog)
    DDRB = (1 << DDB2); // Set PB2 as output, others as input
    
    // Disable pull-up resistors on analog pins
    PORTB &= ~((1 << PORTB0) | (1 << PORTB1));
    
    // Set PB3 as input (button)
    DDRB &= ~(1 << DDB3);
    PORTB |= (1 << PORTB3); // Enable pull-up resistor on PB3
    
    // Configure ADC
    ADMUX = (1 << MUX0); // Select ADC1 (PB1)
    ADCSRA = (1 << ADEN) | (3 << ADPS0); // Enable ADC, prescaler 64 (for 1 MHz clock)
}

void RelayOn() {
    PORTB |= (1 << PB2); // Set PB2 high
}

void RelayOff() {
    PORTB &= ~(1 << PB2); // Set PB2 low
}

void RelayToggle() {
    PORTB ^= (1 << PB2); // Toggle PB2
}

void DelayTime(uint16_t delay_ms) {
    while (delay_ms >= 1000) {
        _delay_ms(1000);
        delay_ms -= 1000;
    }
    while (delay_ms > 0) {
        _delay_ms(1);
        delay_ms--;
    }
}

uint16_t ReadAnalogPin(uint8_t pin) {
    ADMUX = (ADMUX & 0xF0) | (pin & 0x0F); // Select the ADC pin
    ADCSRA |= (1 << ADSC); // Start the conversion
    while (ADCSRA & (1 << ADSC)); // Wait for conversion to complete
    uint16_t result = ADCL; // Read lower byte    
    return result;
}

I am ok Arduino platform . I need sample code to digitalpin Pb3 and Blink LED,

also analogpin to read value and blink LED. Since UART wont work to print countvalue i need help in getting value

This sample code i wanna try. I need help in reducing size .

#include <stdint.h>

#define RELAY_PIN 2
#define DIP4_PIN 3
#define DIP_SWITCH A0
#define RANGE_POT A1

#define DELAY_1SEC      1000
#define DELAY_10SEC     10000
#define DELAY_30SEC     30000
#define DELAY_1MIN      60000
#define DELAY_3SEC      3000
#define DELAY_10MIN     600000
#define DELAY_30MIN     1800000
#define DELAY_1HR       3600000
#define DELAY_3HR       10800000
#define DELAY_30HR      108000000
#define DELAY_3MIN      180000

int DIP_Value = 0;
int POT_Read = 0;

void setup() {
    pinMode(RELAY_PIN, OUTPUT);
    pinMode(DIP4_PIN, INPUT);
}

void loop() {
    DIP_Value = analogRead(DIP_SWITCH);
    POT_Read = analogRead(RANGE_POT);
    
    uint32_t baseDelay = getBaseDelay(DIP_Value, digitalRead(DIP4_PIN));
    uint32_t scaledDelay = scaleDelay(baseDelay, POT_Read);
    
    
   delay(scaledDelay);
   digitalWrite(RELAY_PIN, HIGH);
}

uint32_t getBaseDelay(uint16_t DIP_Value, char DIP4_state) {
    if (DIP_Value <= 16) {
        return (DIP4_state == LOW) ? DELAY_1SEC : DELAY_1MIN;
    } else if (DIP_Value <= 32) {
        return DELAY_1HR;
    } else if (DIP_Value <= 50) {
        return (DIP4_state == LOW) ? DELAY_10SEC : DELAY_10MIN;
    } else if (DIP_Value <= 67) {
        return DELAY_10MIN;
    } else if (DIP_Value <= 84) {
        return (DIP4_state == LOW) ? DELAY_3SEC : DELAY_3MIN;
    } else if (DIP_Value <= 104) {
        return DELAY_3HR;
    } else if (DIP_Value <= 118) {
        return (DIP4_state == LOW) ? DELAY_30SEC : DELAY_30MIN;
    } else if (DIP_Value <= 135) {
        return DELAY_30HR;
    }
    return DELAY_1SEC;  // Default case
}

uint32_t scaleDelay(uint32_t baseDelay, uint16_t POT_Value) {
    uint8_t multiplier = (POT_Value / 10) + 1;  // Ensures multiplier is at least 1
    return baseDelay * multiplier;
}

What help?

byte ledPin = PB0; //
byte potPin = PB3; // ADC1
byte minPot = 0;
byte maxPot = 1023;
byte minLED = 100;
byte maxLED = 1000;

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

void loop() {
  delay(map(analogRead(potPin), minPot, maxPot, minLED, maxLED));
  digitalWrite(ledPin, !digitalRead(ledPin));
}

I'm trying to reduce code size on an Arduino. Using libraries consumes 95% of memory, while avoiding them still uses 75%. Additionally, I'm struggling with analog and digital pin reading. For example, if TimeSection returns 1 second, how can I calculate a count in the range of 1-10, corresponding to intervals from 0.1 to 1 second? Any advice on optimizing memory and formula for this?

Application is on delay timer . Range 1-10 value , DIP switch along with Digital pin gives range 0.1Sec-30Hr. first read DIP and digtial pin and return Timing required for on the relay. Later Range we devide by pot value 1-10 based to get good accuracy.

Example 1Sec selected means Range can be 0.1Sec to 1Sec based on pot position.
Based on range and time-interval relay will be on.

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

#define F_CPU 1000000UL // Define CPU frequency as 1MHz
#include <util/delay.h>

// ADC channel definitions
#define POT_CHANNEL 0 // ADC channel for potentiometer
#define DIP_CHANNEL 1 // ADC channel for DIP switch

// Digital pin definitions
#define DIP_PIN 3 // Example digital pin (PB3)

#define DELAY_0_1SEC    100   // 100 milliseconds
// Delay constants (in milliseconds)
#define DELAY_1SEC      1000
#define DELAY_10SEC     10000
#define DELAY_30SEC     30000
#define DELAY_1MIN      60000
#define DELAY_3SEC      3000
#define DELAY_3MIN      180000
#define DELAY_10MIN     600000
#define DELAY_30MIN     1800000
#define DELAY_1HR       3600000
#define DELAY_3HR       10800000
#define DELAY_10HR      36000000 // Added delay for 10 hours
#define DELAY_30HR      108000000

// Mode definitions
#define ON_DELAY_MODE 0
#define INTERVAL_MODE 1

void InitADC(uint8_t channel) {
  ADMUX = (ADMUX & 0xF0) | (channel & 0x0F);
  ADCSRA = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0);
}

uint16_t ReadADC(uint8_t channel) {
  ADMUX = (ADMUX & 0xF0) | (channel & 0x0F);
  ADCSRA |= (1 << ADSC);
  while (ADCSRA & (1 << ADSC)); // Wait for conversion to complete
  return ADCL;
}

void InitIO() {
  DIDR0 = (1 << ADC0D) | (1 << ADC1D); // Disable digital input buffers for ADC pins
  DDRB |= (1 << PB2); // Set PB2 as output (Relay)
  DDRB &= ~(1 << DIP_PIN); // Set DIP_PIN as input
  PORTB |= (1 << DIP_PIN); // Enable pull-up resistor on DIP_PIN
}

void RelayOn() {
  PORTB |= (1 << PB2); // Set PB2 high (Relay on)
}

void RelayOff() {
  PORTB &= ~(1 << PB2); // Set PB2 low (Relay off)
}

uint8_t ReadDIPSwitchDigital() {
  return (PINB & (1 << DIP_PIN)) ? INTERVAL_MODE : ON_DELAY_MODE; // Read digital state
}

uint32_t getBaseDelay(uint16_t DIP_Value, uint8_t DIP4_state) {
  if (DIP_Value <= 16) {
    return (DIP4_state == 0) ? DELAY_1SEC : DELAY_1MIN;
  } else if (DIP_Value <= 32) {
    return DELAY_1HR;
  } else if (DIP_Value <= 50) {
    return (DIP4_state == 0) ? DELAY_10SEC : DELAY_10MIN;
  } else if (DIP_Value <= 67) {
    return DELAY_10MIN;
  } else if (DIP_Value <= 84) {
    return (DIP4_state == 0) ? DELAY_3SEC : DELAY_3MIN;
  } else if (DIP_Value <= 104) {
    return DELAY_3HR;
  } else if (DIP_Value <= 118) {
    return (DIP4_state == 0) ? DELAY_30SEC : DELAY_30MIN;
  } else if (DIP_Value <= 135) {
    return DELAY_10HR; // Return 10 hours delay
  }
  return DELAY_1SEC;
}

uint32_t ReadDIPSwitch(uint8_t mode) {
  // Get digital pin state
  uint8_t dip4State = (PINB & (1 << DIP_PIN)) ? 1 : 0;
  // Read ADC for DIP channel
  uint16_t dipValue = ReadADC(DIP_CHANNEL);

  // Get base delay based on DIP value and state
  return getBaseDelay(dipValue, dip4State);
}

void DelayTime(uint32_t time_ms) {
  while (time_ms >= 1000) {
    _delay_ms(1000); // Delay for 1000 milliseconds
    time_ms -= 1000;
  }
  while (time_ms > 0) {
    _delay_ms(1); // Delay for remaining milliseconds
    time_ms--;
  }
}

int main() {
  InitIO();
  while (1) {
    InitADC(POT_CHANNEL);
    uint16_t potValue = ReadADC(POT_CHANNEL);
    uint32_t range = (potValue / 102) + 1; // Map ADC value to range 1-10

    uint8_t mode = ReadDIPSwitchDigital(); // Determine mode based on DIP switch state
    uint32_t TimeSection = ReadDIPSwitch(mode); // Get base delay in milliseconds
    uint32_t timeValue = TimeSection * range;
    if (mode == ON_DELAY_MODE) {
      DelayTime(timeValue);
      RelayOn();
      _delay_ms(1000); // Example: Keep relay on for 1 second
      RelayOff();
    } else if (mode == INTERVAL_MODE) {
      RelayOn();
      DelayTime(timeValue);
      RelayOff();
      DelayTime(timeValue);
    }
  }

  return 0;
}

count = interval * 10;

Analogread example taken from here

The following program reads the voltage from a potentiometer on analogue input ADC1 (PB1), and then uses this to set the compare match register OCR0A of Timer/Counter0, to generate a square wave on PB0 whose frequency you can control with the potentiometer:

void setup () {
  DDRB = 1;                       // PB0 as an output
  // Set up ADC on PB2
  ADMUX = 1<<MUX0;                // ADC1 (PB1)
  ADCSRA = 1<<ADEN | 3<<ADPS0;    // Enable ADC, 125kHz clock
  // Set up waveform on PB0
  TCCR0A = 1<<COM0A0 | 3<<WGM00;  // Toggle OC0A, Fast PWM
  TCCR0B = 3<<WGM02 | 4<<CS00;    // Fast PWM with OCR0A as TOP; /256
}

void loop () {
  ADCSRA = ADCSRA | 1<<ADSC;      // Start
  while (ADCSRA & 1<<ADSC);       // Wait while conversion in progress
  OCR0A = ADCL;                   // Copy result to frequency output
}

Note that because we're changing the compare match value, we need to use Fast PWM mode in this application, because it double-buffers the compare match value. Here's the circuit:

I Already tried . Can you look into my code and tell correction Needed.
These example already seen. but some extent itnot working

If those examples do not work, there is another problem with your Attiny10, so pointless to look at your code. It also won't work then.

atleast tell how to reduce size here. its working

How much flash and RAM are being consumed by your present sketch? Post the final version of the sketch.

hi @GolamMostafa
Here i pasted my complete code. It just simple on delay timer code. I cant able to debug in arduino IDE. since Serialprint wont support attiny10 mcu.
I have mentioned what are the voltage I am getting in hardware level in comment section.

logic wise

  1. Relay is working
  2. Analog read is working , But not able to set correct count value.

Issue i am facing

  1. timing mismatch void DelayTime(uint32_t time_ms) function creating issue min 100usec and max time is 30Hr calculation to be done
  2. adjusting the ADC count value. I assume its 8 bit adc and adjusted count as per 8 bit
  3. Memory consume 88% currently can we reduce further
#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 1000000UL // Define CPU frequency as 1MHz
#include <util/delay.h>

// ADC channel definitions
#define POT_CHANNEL 0 // ADC channel for potentiometer
#define DIP_CHANNEL 1 // DIP CHannel analog input
#define DIP4_CHANNEL 3 //DIP CHannel analog input
// Digital pin definitions
#define RELAY_PIN 2 // Example digital pin (PB2)

#define DELAY_0_1SEC    100   // 100 milliseconds
// Delay constants (in milliseconds)
#define DELAY_1SEC      1000
#define DELAY_10SEC     10000
#define DELAY_30SEC     30000
#define DELAY_1MIN      60000
#define DELAY_3SEC      3000
#define DELAY_3MIN      180000
#define DELAY_10MIN     600000
#define DELAY_30MIN     1800000
#define DELAY_1HR       3600000
#define DELAY_3HR       10800000
#define DELAY_10HR      36000000 // Added delay for 10 hours
#define DELAY_30HR      108000000

void DelayMicroseconds(uint16_t us) {
  while (us--) {
    _delay_us(1); // This function uses 1 microsecond delay
  }
}

void InitADC(uint8_t channel) {
  ADMUX = (ADMUX & 0xF0) | (channel & 0x0F);
  ADCSRA = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0);
}

uint16_t ReadADC(uint8_t channel) {
  ADMUX = (ADMUX & 0xF0) | (channel & 0x0F);
  ADCSRA |= (1 << ADSC);
  while (ADCSRA & (1 << ADSC)); // Wait for conversion to complete
  return ADCL; // Read ADC value (combining ADCL and ADCH)
}

void InitIO() {
  InitADC(POT_CHANNEL); DelayMicroseconds(5);
  InitADC(DIP_CHANNEL); DelayMicroseconds(5);
  InitADC(DIP4_CHANNEL); DelayMicroseconds(5);
  DIDR0 = (1 << ADC0D) | (1 << ADC1D); // Disable digital input buffers for ADC pins
  DDRB |= (1 << RELAY_PIN); // Set RELAY_PIN as output (Relay)
  
  DelayMicroseconds(10);
}

void RelayOn() {
  PORTB |= (1 << RELAY_PIN); // Set RELAY_PIN high (Relay on)
}

void RelayOff() {
  PORTB &= ~(1 << RELAY_PIN); // Set RELAY_PIN low (Relay off)
}

uint8_t ReadDIPSwitchDigital() {
  return (PINB & (1 << PB3)) ? 1 : 0; // Return 1 if PB3 is high, otherwise return 0
}

uint32_t getBaseDelay(uint16_t DIP_Value, uint8_t DIP4_state) {
  if (DIP_Value <= 20) {
    return (DIP4_state == 0) ? DELAY_1SEC : DELAY_1MIN;
  } else if (DIP_Value <= 50) { // Assume this range corresponds to voltage around 0.845V
    return DELAY_1HR;
  } else if (DIP_Value <= 130) { // Assume this range corresponds to around 1.63V
    return (DIP4_state == 0) ? DELAY_10SEC : DELAY_10MIN;
  } else if (DIP_Value <= 160) { // Assume this range corresponds to around 2.18V
    return DELAY_10HR;
  } else if (DIP_Value <= 180) { // Assume this range corresponds to around 3.0V
    return (DIP4_state == 0) ? DELAY_3SEC : DELAY_3MIN;
  } else if (DIP_Value <= 210) { // Assume this range corresponds to around 3.53V
    return DELAY_3HR;
  } else if (DIP_Value <= 230) { // Assume this range corresponds to around 3.9V
    return (DIP4_state == 0) ? DELAY_30SEC : DELAY_30MIN;
  } else if (DIP_Value <= 255) { // Assume this range corresponds to around 4.3V
    return DELAY_30HR;
  }
  return DELAY_1SEC; // Default delay
}

uint32_t ReadDIPSwitch() {
   uint8_t dipValue;
  uint16_t dip4_Count = ReadADC(DIP4_CHANNEL);
  uint8_t dip4State = (dip4_Count < 200) ? 1 : 0;
  for (uint8_t i=0;i<5;i++)
  {
     dipValue= ReadADC(DIP_CHANNEL);
  }
 
  return getBaseDelay(dipValue, dip4State);
}

void DelayTime(uint32_t time_ms) {
  while (time_ms >= 1000) {
    _delay_ms(1000); // Delay for 1000 milliseconds
    time_ms -= 1000;
  }
  while (time_ms > 0) {
    _delay_ms(1); // Delay for remaining milliseconds
    time_ms--;
  }
}

uint8_t MapPotentiometer(uint8_t adcValue) {
  // Assuming adcValue ranges from 0 to 255 (8-bit ADC)
  if (adcValue >= 230) return 1;  // High range
  if (adcValue >= 200) return 2;  // 0.56V
  if (adcValue >= 170) return 3;  // 1.06V
  if (adcValue >= 140) return 4;  // 1.47V
  if (adcValue >= 110) return 5;  // 1.81V
  if (adcValue >= 80)  return 6;  // 2.28V
  if (adcValue >= 50)  return 7;  // 2.75V
  if (adcValue >= 30)  return 8;  // 3.15V
  if (adcValue >= 10)  return 9;  // 3.61V
  return 9;  // 4.00V and above
}

int main() {
  InitIO();
  RelayOff();
  int PowerOnFlag = 1;
  uint32_t timeValue=0;
  uint8_t potValue=0;
  while (1) {
    if (PowerOnFlag == 1)
    {
      for(uint8_t i=0;i<100;i++)
      {
         potValue = ReadADC(POT_CHANNEL);
      }
    
      uint8_t range = MapPotentiometer(potValue) + 1; // Map to range 1-10
   
      uint32_t TimeSection = ReadDIPSwitch(); // Get base delay in milliseconds
      timeValue = (TimeSection * range) / 10;
      PowerOnFlag = 0;
    }
    DelayTime(timeValue);
    RelayOn();
  }
  return 0;
}

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