/* ATtiny85 Bargraph Voltmeter
David Johnson-Davies - www.technoblogy.com - 20th December 2015
ATtiny85 @ 1 MHz (internal oscillator; BOD disabled)
CM 11/16/24
This works, but WOW, I have no idea how it works.
Not wure if I could adjust the values to have it work
as a voltmeter to measure a battery.
*/
volatile int Display = 0;
#include <TinyDebug.h>
// Display **********************************************
int Line(int n) {
return (1 << n) >> 1;
}
int Bar(int n) {
return ((signed int) 0x8000 >> (15 - n)) ^ 0xFFFF;
}
// Interrupt **********************************************
volatile int Row = 0;
// Interrupt multiplexes display
ISR(TIMER0_COMPA_vect) {
int Data;
Row = (Row + 1) % 5;
DDRB = 0; // Make all pins inputs
if (Row == 0) Data = (Display & 0xC0)>>3 | (Display & 0x20)>>4;
else if (Row == 1) Data = Display & 0x18;
else if (Row == 3) Data = Display >> 8 & 0x03;
else if (Row == 4) Data = (Display & 0x03) | (Display & 0x04)<<1;
else { Display = Bar(ReadADC()/100); return; } // When Row=2 read ADC
PORTB = (PORTB | Data) & ~(1<<Row); // Take row low
DDRB = DDRB | Data | 1<<Row; // Make row an output
}
// Analogue to Digital **********************************
unsigned int ReadADC() {
unsigned char low, high;
ADCSRA = ADCSRA | 1 << ADSC; // Start
do ; while (ADCSRA & 1 << ADSC); // Wait while conversion in progress
low = ADCL;
high = ADCH;
return (high << 8 | low);
}
// Setup **********************************************
void setup() {
Debug.begin();
// Set up Timer/Counter0 to generate 625Hz interrupt
TCCR0A = 1 << WGM01; // CTC mode
//Debug.println(TCCR0A);
TCCR0B = (1 << CS00) | (1 << CS01); // /64 prescaler
//Debug.println(TCCR0B);
OCR0A = 24; // 625 Hz interrupt
TIMSK = TIMSK | 1 << OCIE0A; // Enable interrupt
// Set up ADC
ADMUX = 2 << REFS0 | 1 << REFS2 | 1 << MUX0; // Internal 2.56V ref, ADC1 (PB2)
ADCSRA = 1 << ADEN | 4 << ADPS0; // Enable, 62.5kHz ADC clock
}
void loop() {
}