Skip to content

Instantly share code, notes, and snippets.

@TamojitSaha
Last active June 27, 2020 19:05
Show Gist options
  • Save TamojitSaha/403f820dc84832bcd2c4ded318da2654 to your computer and use it in GitHub Desktop.
Save TamojitSaha/403f820dc84832bcd2c4ded318da2654 to your computer and use it in GitHub Desktop.
Reading ADC and configuring watchdog in ATtiny85
/*
Update 27 Jun 20
Implemented NRFLite Library for 2pin communication with NRF24L01
Refer to https://github.com/dparson55/NRFLite for more information.
@author: Tamojit Saha
@website: https://www.tamojitsaha.info
*/
#include <avr/sleep.h> // Sleep Modes
#include <avr/power.h>
#include <avr/wdt.h>
const byte LED = 4;
volatile boolean f_wdt = 1;
#define DEBUG
#ifdef DEBUG
#include <SoftwareSerial.h>
SoftwareSerial mySerial(0, 1); // RX, TX
#endif
void setup() {
// put your setup code here, to run once:
pinMode(LED, OUTPUT);
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
initWDT(7);
#ifdef DEBUG
mySerial.begin(4800);
mySerial.println("Hello, world?");
#endif
}
void loop() {
if (f_wdt == 1) { // wait for timed out watchdog / flag is set when a watchdog timeout occurs
f_wdt = 0; // reset flag
digitalWrite(LED, HIGH); // let led blink
delay(200);
#ifdef DEBUG
mySerial.println("ADC3: " + String(readADC(3)));
#endif
digitalWrite(LED, LOW);
pinMode(LED, INPUT); // set all used port to intput to save power
goToSleep();
pinMode(LED, OUTPUT); // set all ports into state before sleep
}
}
int readADC(byte pin) {
/* this function initialises the ADC
For more information, see table 17.5 "ADC Prescaler Selections" in
chapter 17.13.2 "ADCSRA – ADC Control and Status Register A"
(pages 140 and 141 on the complete ATtiny25/45/85 datasheet, Rev. 2586M–AVR–07/10)
// 10-bit resolution
// set ADLAR to 0 to disable left-shifting the result (bits ADC9 + ADC8 are in ADC[H/L] and
// bits ADC7..ADC0 are in ADC[H/L])
// use uint16_t variable to read ADC (intead of ADCH or ADCL)
*/
constrain(pin, 0, 3);
ADMUX =
(0 << ADLAR) | // do not left shift result (for 10-bit values)
(0 << REFS2) | // Sets ref. voltage to Vcc, bit 2
(0 << REFS1) | // Sets ref. voltage to Vcc, bit 1
(0 << REFS0); // Sets ref. voltage to Vcc, bit 0
// ADMUX =
// (0 << ADLAR) | // do not left shift result (for 10-bit values)
// (1 << REFS2) | // Sets ref. voltage to internal 2.56, bit 2
// (1 << REFS1) | // Sets ref. voltage to internal 2.56, bit 1
// (0 << REFS0); // Sets ref. voltage to internal 2.56, bit 0
switch (pin) {
case 0 : ADMUX |=
(0 << MUX3) | // use ADC0 for input (PB5), MUX bit 3
(0 << MUX2) | // use ADC0 for input (PB5), MUX bit 2
(0 << MUX1) | // use ADC0 for input (PB5), MUX bit 1
(0 << MUX0);
DIDR0 |= (1 << ADC0D); // disable digital input buffer on ADC0
break;
case 1 : ADMUX |=
(0 << MUX3) | // use ADC1 for input (PB2), MUX bit 3
(0 << MUX2) | // use ADC1 for input (PB2), MUX bit 2
(0 << MUX1) | // use ADC1 for input (PB2), MUX bit 1
(1 << MUX0);
DIDR0 |= (1 << ADC1D); // disable digital input buffer on ADC0
break;
case 2 : ADMUX |=
(0 << MUX3) | // use ADC2 for input (PB4), MUX bit 3
(0 << MUX2) | // use ADC2 for input (PB4), MUX bit 2
(1 << MUX1) | // use ADC2 for input (PB4), MUX bit 1
(0 << MUX0);
DIDR0 |= (1 << ADC2D); // disable digital input buffer on ADC0
break;
case 3 : ADMUX |=
(0 << MUX3) | // use ADC3 for input (PB3), MUX bit 3
(0 << MUX2) | // use ADC3 for input (PB3), MUX bit 2
(1 << MUX1) | // use ADC3 for input (PB3), MUX bit 1
(1 << MUX0);
DIDR0 |= (1 << ADC3D); // disable digital input buffer on ADC0
break;
}
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
uint8_t adc_lobyte; // to hold the low byte of the ADC register (ADCL)
uint16_t raw_adc;
ADCSRA |= (1 << ADSC); // start ADC measurement
while (ADCSRA & (1 << ADSC) ); // wait till conversion complete
// for 10-bit resolution:
adc_lobyte = ADCL; // get the sample value from ADCL
raw_adc = ADCH << 8 | adc_lobyte; // add lobyte and hibyte
return raw_adc;
}
void initWDT(byte frequency) {
byte temp;
temp = frequency & 7;
if (frequency > 7) temp |= (1 << 5);
temp |= (1 << WDCE); //Datasheet Page 46, This bit must also be set when changing the prescaler bit
MCUSR &= ~(1 << WDRF);
// start timed sequence
WDTCR |= (1 << WDCE) | (1 << WDE);
// set new watchdog timeout value
WDTCR = temp;
WDTCR |= 1 << WDIE;
}
ISR(WDT_vect) {
f_wdt = 1; // set global flag
}
void goToSleep ()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
ADCSRA = 0; // turn off ADC
power_all_disable (); // power off ADC, Timer 0 and 1, serial interface
sleep_enable();
sleep_bod_disable();
sleep_cpu();
sleep_disable();
power_all_enable(); // power everything back on
} // end of goToSleep
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment