Last active
June 27, 2020 19:05
-
-
Save TamojitSaha/403f820dc84832bcd2c4ded318da2654 to your computer and use it in GitHub Desktop.
Reading ADC and configuring watchdog in ATtiny85
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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