I'm using the analog input of a voltage divider made of a thermistor (10k) and a fixed resistor (12k), to monitor a variation in temperature using the Ladyada code.
Ladyada's code is very versatile and works as expected. My goal is to add a buzzer that will beep more frequently as the temperature rises. Since I dont have any buzzer right now, I have been testing my ideas with an LED.
Initially I went with a simple ON/OFF delay: fixed On delay(100) for short beeps and an OFF delay that would start at around 2000ms and become shorter as temp increased. This worked well but using "delay"...delays everything else happening, which sucks.
Using Millis() also worked, however, it meant that the LED would stay ON for 2000ms and OFF for another 2000ms, when it's blinking at the lowest rate (lowest temp). This would mean having a buzzer ON for 2 seconds, which I dont want.
// which analog pin to connect
#define THERMISTORPIN A0
// resistance at 25 degrees C
#define THERMISTORNOMINAL 10000
// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25
// how many samples to take and average, more takes longer
// but is more 'smooth'
#define NUMSAMPLES 5
// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT 3900
// the value of the 'other' resistor
#define SERIESRESISTOR 12000
//#define DEBUG
int samples[NUMSAMPLES];
int ledPin = 9;
int outputValue = 0;
unsigned long previousMillis = 0;
int ledState = LOW;
void setup(void) {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
analogReference(EXTERNAL);
}
void loop(void) {
uint8_t i;
float average;
// take N samples in a row, with a slight delay
for (i=0; i< NUMSAMPLES; i++) {
samples[i] = analogRead(THERMISTORPIN);
delay(10);
}
// average all the samples out
average = 0;
for (i=0; i< NUMSAMPLES; i++) {
average += samples[i];
}
average /= NUMSAMPLES;
// convert the value to resistance
average = 1023 / average - 1;
average = SERIESRESISTOR / average;
float steinhart;
steinhart = average / THERMISTORNOMINAL; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro)
steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // convert to C
// map the temperature variating from 19-30 ºC to a delay value, smaller delay faster blink
outputValue = map(steinhart, 19, 30, 2000, 10);
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= outputValue) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
//Basic delay alternative
/*digitalWrite(ledPin, HIGH);
delay(10);
digitalWrite(ledPin, LOW);
delay(outputValue);*/
#if defined DEBUG
Serial.print("Average analog reading ");
Serial.println(average);
Serial.print("Thermistor resistance ");
Serial.println(average);
Serial.print("Temperature ");
Serial.print(steinhart);
Serial.println(" *C");
Serial.print("outputValue ");
Serial.println(outputValue);
delay(100);
#endif
;
}
if (currentMillis - previousMillis >= outputValue) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
When you change the value of "ledState", you could also change the value of the ON time (currently "outputValue") or the OFF time.
Solved: the LED blinks more frequently as the temp rises
// which analog pin to connect
#define THERMISTORPIN A0
// resistance at 25 degrees C
#define THERMISTORNOMINAL 10000
// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25
// how many samples to take and average, more takes longer
// but is more 'smooth'
#define NUMSAMPLES 5
// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT 3900
// the value of the 'other' resistor
#define SERIESRESISTOR 12000
// number of samples
int samples[NUMSAMPLES];
// On and Off Times (as int, max=32secs)
const unsigned int onTime = 100;
int offTime = 0;
// Tracks the last time event fired
unsigned long previousMillis=0;
// Interval is how long we wait
int interval = onTime;
// Used to track if LED should be on or off
boolean ledState = true;
const int ledPin = 9;
int outputValue = 0;
//#define DEBUG
void setup(void) {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
analogReference(EXTERNAL);
}
void loop(void) {
uint8_t i;
float average;
// take N samples in a row, with a slight delay
for (i=0; i< NUMSAMPLES; i++) {
samples[i] = analogRead(THERMISTORPIN);
delay(10);
}
// average all the samples out
average = 0;
for (i=0; i< NUMSAMPLES; i++) {
average += samples[i];
}
average /= NUMSAMPLES;
// convert the value to resistance
average = 1023 / average - 1;
average = SERIESRESISTOR / average;
float steinhart;
steinhart = average / THERMISTORNOMINAL; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro)
steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // convert to C
// map the temperature variating from 19-30 ºC to a delay value, smaller delay faster blink
outputValue = map(steinhart, 19, 40, 2000, 10);
// Set Pin ledPin to state of ledState each timethrough loop()
// If ledState hasn't changed, neither will the pin
digitalWrite(ledPin, ledState);
// Grab snapshot of current time, this keeps all timing
// consistent, regardless of how much code is inside the next if-statement
unsigned long currentMillis = millis();
// Compare to previous capture to see if enough time has passed
if ((unsigned long)(currentMillis - previousMillis) >= interval) {
// Change wait interval, based on current LED state
if (ledState) {
// LED is currently on, set time to stay off
interval = outputValue;
} else {
// LED is currently off, set time to stay on
interval = onTime;
}
// Toggle the LED's state, Fancy, eh!?
ledState = !(ledState);
// Save the current time to compare "later"
previousMillis = currentMillis;
#if defined DEBUG
Serial.print("Average analog reading ");
Serial.println(average);
Serial.print("Thermistor resistance ");
Serial.println(average);
Serial.print("Temperature ");
Serial.print(steinhart);
Serial.println(" *C");
Serial.print("outputValue ");
Serial.println(outputValue);
delay(50);
#endif
}
}
Alternative: the pitch of a buzzer increases as temperature rises
// which analog pin to connect
#define THERMISTORPIN A0
// resistance at 25 degrees C
#define THERMISTORNOMINAL 10000
// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25
// how many samples to take and average, more takes longer
// but is more 'smooth'
#define NUMSAMPLES 5
// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT 3900
// the value of the 'other' resistor
#define SERIESRESISTOR 12000
// number of samples
int samples[NUMSAMPLES];
// On and Off Times (as int, max=32secs)
const unsigned int onTime = 100;
int offTime = 0;
// Tracks the last time event fired
unsigned long previousMillis=0;
// Interval is how long we wait
int interval = onTime;
// Used to track if LED should be on or off
boolean ledState = true;
const int ledPin = 9;
int outputValue = 0;
//#define DEBUG
void setup(void) {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
analogReference(EXTERNAL);
}
void loop(void) {
uint8_t i;
float average;
// take N samples in a row, with a slight delay
for (i=0; i< NUMSAMPLES; i++) {
samples[i] = analogRead(THERMISTORPIN);
delay(10);
}
// average all the samples out
average = 0;
for (i=0; i< NUMSAMPLES; i++) {
average += samples[i];
}
average /= NUMSAMPLES;
// convert the value to resistance
average = 1023 / average - 1;
average = SERIESRESISTOR / average;
float steinhart;
steinhart = average / THERMISTORNOMINAL; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro)
steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // convert to C
// map the temperature variating from 19-30 ºC to a delay value, smaller delay faster blink
outputValue = map(steinhart, 19, 40, 0, 800);
int pitch = 200 + outputValue;
tone(ledPin, pitch);
#if defined DEBUG
Serial.print("Average analog reading ");
Serial.println(average);
Serial.print("Thermistor resistance ");
Serial.println(average);
Serial.print("Temperature ");
Serial.print(steinhart);
Serial.println(" *C");
Serial.print("outputValue ");
Serial.println(outputValue);
delay(50);
#endif
}