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;
}
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;
}
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:
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
Relay is working
Analog read is working , But not able to set correct count value.
Issue i am facing
timing mismatch void DelayTime(uint32_t time_ms) function creating issue min 100usec and max time is 30Hr calculation to be done
adjusting the ADC count value. I assume its 8 bit adc and adjusted count as per 8 bit
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;
}