void CPU_8MHz() { cli(); CLKPR = 0b10000000; CLKPR = 0b00000000; // Clock divider: 1 sei(); // USART0 UCSR0A = UCSR0A | 0b00000010; // Enable double speed UBRR0 = 0x0067; // 9600bps } void CPU_4MHz() { cli(); CLKPR = 0b10000000; CLKPR = 0b00000001; // Clock divider: 2 sei(); // USART0 UCSR0A = UCSR0A | 0b00000010; // Enable double speed UBRR0 = 0x0033; // 9600bps } void CPU_2MHz() { cli(); CLKPR = 0b10000000; CLKPR = 0b00000010; // Clock divider: 4 sei(); // USART0 UCSR0A = UCSR0A | 0b00000010; // Enable double speed UBRR0 = 0x0019; // 9600bps } void CPU_1MHz() { cli(); CLKPR = 0b10000000; CLKPR = 0b00000011; // Clock divider: 8 sei(); // USART0 UCSR0A = UCSR0A | 0b00000010; // Enable double speed UBRR0 = 0x000C; // 9600bps } void setup() { #ifdef HAVE_HWSERIAL0 CPU_8MHz(); Serial.begin(9600); Serial.println(F("Internal Temperature Sensor")); Serial.flush(); // UBRR0 = 0x0033; CPU_1MHz(); Serial.println(F("Serial test at 1MHz clock speed.")); Serial.flush(); CPU_2MHz(); Serial.println(F("Serial test at 2MHz clock speed.")); Serial.flush(); CPU_4MHz(); Serial.println(F("Serial test at 4MHz clock speed.")); Serial.flush(); CPU_8MHz(); Serial.println(F("Serial test at 8MHz clock speed.")); Serial.flush(); CPU_1MHz(); #endif } void loop() { // Show the temperature in degrees Celcius. #ifdef HAVE_HWSERIAL0 CPU_8MHz(); Serial.print(F("Temperature: ")); Serial.println(getChipTemp(), 2); Serial.print(F("Voltage: ")); Serial.println(getVCCVoltage(), 2); Serial.flush(); CPU_1MHz(); #else getChipTemp(); getVCCVoltage(); #endif delay(1000); } double getChipTemp() { uint16_t wADC; // Set the internal reference and mux. #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined (__AVR_ATtiny85__) ADMUX = 0b10001111; // REFS2 = 0; REFS1 = 1; REFS0 = 0; MUX3:0 = 0b1111 // Reference = 1.1V, Measure ADC4 (Temperature) #elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined (__AVR_ATtiny84__) ADMUX = 0b10100010; // REFS1 = 1; REFS0 = 0; MUX5:0 = 0b100010 // Reference = 1.1V, Measure ADC8 (Temperature) #elif defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) ADMUX = 0b11001000; // REFS1 = 1; REFS0 = 1; MUX3:0 = 0b1000 // Reference = 1.1V, Measure ADC8 (Temperature) #else #error Unknown CPU type, not implemented. #endif ADCSRA |= _BV(ADEN); // enable the ADC delay(10); // wait for voltages to become stable. ADCSRA |= _BV(ADSC); // Start the ADC // Detect end-of-conversion while (bit_is_set(ADCSRA,ADSC)); // Reading register "ADCW" takes care of how to read ADCL and ADCH. wADC = ADCW; // The offset of 324.31 could be wrong. It is just an indication. return (wADC - 314.0d) / 1.22d; } double getVCCVoltage() { uint16_t wADC; // Set the internal reference and mux. #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined (__AVR_ATtiny85__) ADMUX = 0b00001110; // REFS2 = 0; REFS1 = 0; REFS0 = 0; MUX3:0 = 0b1100 // Reference = VCC, Measure 1.1V(VBG) bandgap #elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined (__AVR_ATtiny84__) ADMUX = 0b00100001; // REFS1 = 0; REFS0 = 0; MUX5:0 = 0b100001 // Reference = VCC, Measure 1.1V(VBG) bandgap #elif defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) ADMUX = 0b01001110; // REFS1 = 0; REFS0 = 1; MUX3:0 = 0b1110 // Reference = AVCC, Measure 1.1V(VBG) bandgap #else #error Unknown CPU type, not implemented. #endif ADCSRA |= _BV(ADEN); // enable the ADC delay(10); // wait for voltages to become stable. ADCSRA |= _BV(ADSC); // Start the ADC while (bit_is_set(ADCSRA, ADSC)); // Wait for conversion to finish. wADC = ADCW; return wADC ? (1.1d * 1023) / wADC : -1; }