Taking and displaying 10 temperature measurements

We are here to help you learn to code, not write code for you. The gigs and collaborations section is for people to have someone write code for them, usually for pay.

If you have tried to write the code, post it here and give a description of what it does and what you want it to do.

I would like to help you with your project. Can you provide a schematic of the setup? Please include component values and part numbers.

Hi groundfungus,

I'm just using the components that come in the Arduino starter kit.

The LEDs are connected to inputs 2 and 3 with 220 Ohm resistors on the returns.
The pushbuttons are connected to inputs 6 and 7 with 10 kOhms resistors on the returns.
The temperature sensor is TM36 and connected to input A0.

The pushbuttons are connected to inputs 6 and 7 with 10 kOhms resistors on the returns.

OK, first suggestion is to wire the button switches from ground to the input pin. Lose the 10K resistor. In setup you will enable the internal pullup resistor with the pinMode(pin, INPUT_PULLUP) statement. Put a 100nf cap across the switch (to ground and the input). The cap will help to debounce the switch to give clean transitions.

The LEDs are connected to inputs 2 and 3 with 220 Ohm resistors on the returns.

May just be semantics, but LEDs connected to inputs are not much good. Outputs makes more sense.

I will start to work on the code with the above in mind and get back when I have a start.

Thanks groundfungus. Regards the LEDs I meant outputs. That was a typo.

Here is my terrible code so far:

<#include <EEPROM.h>

int detectionswitch = 0;
int measurementswitch = 0;
const int sensorPin = A0;

void setup()
{
// open a serial port:
Serial.begin(9600);

// LED outputs:
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);

// switch inputs:
pinMode(6, INPUT);
pinMode(7, INPUT);
}

void loop() {
detectionswitch = digitalRead(6);
measurementswitch = digitalRead(7);

// standby mode:
Serial.println("STAND-BY MODE");
if (detectionswitch == LOW)
{
digitalWrite(2, HIGH);
delay(250);
digitalWrite(2, LOW);
delay(1750);
}

// measurement mode:
else
{
Serial.println("MEASUREMENT MODE. ");

for (int counter = 0; counter < 10; counter++)
{
Serial.print("Count: ");
Serial.print(counter+1);
int sensorVal = analogRead(sensorPin);
float voltage = (sensorVal/1024.0) * 5.0;
float temperature = (voltage - .5) * 100;

Serial.print(". \t Sensor value: ");
Serial.print(sensorVal);
Serial.print(". \t Voltage: ");
Serial.print(voltage);
Serial.print(" V. \t Temperature: ");
Serial.println(temperature);
digitalWrite(3, HIGH);
delay(250);
digitalWrite(3, LOW);
delay(500);
}
}
}

Here is my attempt. I use a state machine to organize the steps and blink without delay method for timing. Let me know if this is what you want. I see that you include the EEPROM library. Saving to EEPROM should be pretty easy, just add a state and use button b to save when in standby after measurement complete. You will need to save the values to an array as they are recorded.

Note that my buttons are wired like I described before (from ground to input with 100nf cap across switch) so they are LOW when pushed.

/*
By C. Goulding
 temperature sensing and transmission program for forum poster
 using AD22100 temperature sensor in lieu of TMP36 sensor for now
 */


const byte ledAPin = 2;
const byte ledBPin = 3;
const byte buttonAPin = 6;
const byte buttonBPin = 7;
const byte tempInPin = A0;

// to keep track of state
byte state = 0;

// button variables
byte buttonACounter = 0;   // counter for the number of button presses
boolean buttonAState = HIGH;         // current state of the button
boolean lastButtonAState = HIGH;

byte buttonBCounter = 0;   // counter for the number of button presses
boolean buttonBState = HIGH;         // current state of the button
boolean lastButtonBState = HIGH;

// timers
unsigned long ledATimer, ledAlastTime;
unsigned long ledAInterval = 500;

unsigned long ledBTimer, ledBlastTime;
unsigned long ledBInterval = 500;

unsigned long measTimer, measlastTime;
unsigned long measInterval = 5000;

unsigned long currentMillis;


boolean isMeasInit = false;
boolean isSBInit = false;
byte measIndex = 0;
byte numMeasurements = 10;

void setup()
{
    Serial.begin(9600);
    delay(1000);
    pinMode(buttonAPin, INPUT_PULLUP);  
    pinMode(buttonBPin, INPUT_PULLUP);
    pinMode(ledAPin, OUTPUT);
    pinMode(ledBPin, OUTPUT);
    Serial.print(F("Program started \n"));

}

void loop()
{
    // time for timers
    currentMillis = millis();
    
    switch(state)
    {
    case 0: // standby
        //print "standby" once
        if(isSBInit == false)
        {
            Serial.println(F("STAND-BY MODE"));
            isSBInit = true;
        }
        // blink the led
        blinkLedA();
        // check button, if pushed go to measurement mode (state 1)
        if(ckButtonA() == true)
        {
            digitalWrite(ledAPin, LOW);
            isMeasInit = false;
            measIndex = 0;
            state = 1;
        }
        break;
    case 1:  //measure
        // print "measur mode" once
        if(isMeasInit == false)
        {
            Serial.println(F("MEASUREMENT MODE. "));
            isMeasInit = true;
            measTimer = currentMillis;
        }
        
        blinkLedB();
        // button a to abort back to sb
        if(ckButtonA() == true)  // back to standby
        {
            digitalWrite(ledBPin, LOW);
            isSBInit = false; // display message again
            state = 0;
        }
        // take measurements
        
        if(currentMillis - measTimer > measInterval) // has 5 sec elapsed?
        //if so print missed and check for done
        {
            Serial.println(F("MISSED"));
            if(measIndex > numMeasurements - 2)  // got ten go to SB
            {
                isSBInit = false;
                measIndex = 0;
                Serial.println(F("measurement complete"));
                state = 0;
            }
            measIndex++;
            measTimer = currentMillis;
        }
        // take and send on button press
        if(ckButtonB() == true)
        {

            Serial.print(F("Measurement # "));
            Serial.print(measIndex);
            Serial.print(F(" Temp C = "));
            Serial.println(getTemp());
            if(measIndex > numMeasurements - 2)  // got ten go to SB
            {
                isSBInit = false;
                digitalWrite(ledBPin, LOW);
                measIndex = 0;
                Serial.println(F("measurement complete"));
                state = 0;
            }
            measIndex++;
            measTimer = currentMillis;
        }
        break;
    }

}

float getTemp()  // using ad22100 temp sensor
{
    int rawin = analogRead(tempInPin);
    float vin = rawin * (5.0/1023.0);
    float tempc = (vin-1.375) / 0.0225;
    float tempf =  1.8*tempc+32;
    return tempc;
}

void blinkLedA()
{
    if(currentMillis - ledATimer > ledAInterval)
    {
        digitalWrite(ledAPin, !digitalRead(ledAPin));
        ledATimer = currentMillis;
    }
}

void blinkLedB()
{
    if(currentMillis - ledBTimer > ledBInterval)
    {
        digitalWrite(ledBPin, !digitalRead(ledBPin));
        ledBTimer = currentMillis;
    }
}

boolean ckButtonA()
{
    boolean pushed = false;
    buttonAState = digitalRead(buttonAPin);
    if (buttonAState != lastButtonAState) {
        if (buttonAState == LOW) {
            buttonACounter++;
            pushed = true;
        }
        else {
            pushed = false;
        }
    }
    lastButtonAState = buttonAState;
    return pushed;
}

boolean ckButtonB()
{
    boolean pushed = false;
    buttonBState = digitalRead(buttonBPin);
    if (buttonBState != lastButtonBState) {
        if (buttonBState == LOW) {
            buttonBCounter++;
            pushed = true;
        }
        else {
            pushed = false;
        }
    }
    lastButtonBState = buttonBState;
    return pushed;
}

/*Standby mode
 blinking LED
 *button A pressed*
 Measurement mode
 *button B pressed within 5 s*
 Count 1:  Temp = 30 C
 *button B pressed within 5 s*
 Count 2: Temp = 35 C
 *button B not pressed within 5 s*
 Count 3: Temp - missed.
 repeats until count 10 and returns to standby mode.

 Voltage at pin in milliVolts = (reading from ADC) * (5000/1024)
 This formula converts the number 0-1023 from the ADC into 0-5000mV (= 5V)

 Then, to convert millivolts into temperature, use this formula:
 Centigrade temperature = [(analog voltage in mV) - 500] / 10
 */

Hello groundfungus,

Thank you ever so much. Your code is brilliant! I've just tried it and it works very well. The only thing I would change is to make it so, once measurement mode has started, pressing button A has no effect. Can you help me with that?

groundfungus:
I use a state machine to organize the steps and blink without delay method for timing. Let me know if this is what you want.

Sorry, I haven't got a clue what that means, so I don't know if I want it or not!

groundfungus:
I see that you include the EEPROM library. Saving to EEPROM should be pretty easy, just add a state and use button b to save when in standby after measurement complete. You will need to save the values to an array as they are recorded.

Yes, I do want to save the measurements to memory. Can this to happen automatically rather than pressing button B? and I really want to send them via a wireless communications link to a computer.

groundfungus, can you help with any of this please?

Again, many thanks for this.

The only thing I would change is to make it so, once measurement mode has started, pressing button A has no effect. Can you help me with that?

Remove these lines to disable abort with button A during measure mode

// button a to abort back to sb
        if(ckButtonA() == true)  // back to standby
        {
            digitalWrite(ledBPin, LOW);
            isSBInit = false; // display message again
            state = 0;
        }

Quote from: groundfungus on Nov 28, 2015, 06:20 pm

I use a state machine to organize the steps and blink without delay method for timing. Let me know if this is what you want.

Sorry, I haven't got a clue what that means, so I don't know if I want it or not!

My turn to be sorry. What I meant was does the code (in its entirety) do what you want.
A state machine is a way of programming that breaks the program into a number of states. In this case I had a standby state and a measure state. That way it is easy to add on to the program, just add states and call each state depending on the program's inputs.

Yes, I do want to save the measurements to memory. Can this to happen automatically rather than pressing button B? and I really want to send them via a wireless communications link to a computer.

So you will push button A and the program will take 10 measurements and save to memory (EEPROM)?
How much time between readings? Button B is no longer used at all? Please describe, in detail, how the program will flow once the button A is pushed.

As for the wireless part I have to ask, what is the distance for the data to be transmitted? The answer to that question is necessary to be able to choose a wireless method. What is at the receiving end? I mean just to serial monitor or do you have a program on the PC to receive and process the data?

I am happy to help. Over the last few years I have been learning and have written many many sketches for myself. It is rewarding to me to put my learning to use for others.

Start here and explore the rabbit hole :slight_smile:

Finite state machine: wikipedia.

groundfungus:
I mean just to serial monitor or do you have a program on the PC to receive and process the data?

Or do you need to have that program written also?

groundfungus:
So you will push button A and the program will take 10 measurements and save to memory (EEPROM)?
How much time between readings? Button B is no longer used at all? Please describe, in detail, how the program will flow once the button A is pushed.

I want button A to do is act as a trigger to switch the device out of standby mode. I plan to power this device by batteries so I want as little power consumption as possible. My rationale in saving the 10 measurements to memory is in case the communications link is busy.

Button B simulates a detector which detects the passing targets. As soon a button B detects the target, I need it to take the temperature. The targets pass in groups of 10, but may vary in speed. The target is only 30 mm in diameter and could be passing at a speeds up to 10 m/s so the reading could be as quick as 3 ms. The minimum time between readings would be approximately 150 ms.

Once the 10 measurements have been successfully transmitted, they can be deleted. Then the device can return to standby mode. The only trouble would be if another set of 10 targets comes along before the first set of 10 have been sent.

groundfungus:
As for the wireless part I have to ask, what is the distance for the data to be transmitted? The answer to that question is necessary to be able to choose a wireless method. What is at the receiving end? I mean just to serial monitor or do you have a program on the PC to receive and process the data?

The maximum distance would be 1 km. More likely 500 m. I was hoping that it would be received and sent to a PC. The PC would then display an alarm if any of the targets are overheating. I don't have a program to do this yet.

groundfungus:
I am happy to help. Over the last few years I have been learning and have written many many sketches for myself. It is rewarding to me to put my learning to use for others.

Thanks, that's very kind.

I want button A to do is act as a trigger to switch the device out of standby mode. I plan to power this device by batteries so I want as little power consumption as possible. My rationale in saving the 10 measurements to memory is in case the communications link is busy.

Writing to 10 float values to EEPROM is no problem. Using a full up Uno is problematic when considering low power. The USB-serial subsystem, various LEDs, running at 16Mhz, etc consume power (around 50 mA, I think). A stand alone 328 running at 8Mhz can consume less than 1/4 the power. Then there is sleeping the processor (something new for me) to get current consumption into the micro amp range. low power

Button B simulates a detector which detects the passing targets. As soon a button B detects the target, I need it to take the temperature. The targets pass in groups of 10, but may vary in speed.

Is button B is some sort of detector? What exactly? So the sampling of the temperature for each object triggered by the "button B detector" as well as sensing the arrival of the first object? So, button A is pressed, the unit enters measurement mode, the detector senses the first of ten, takes the reading, stores the reading, senses and reads 9 more objects and reads each of their temperatures, storing each reading then returns to standby? Now the temperatures are stored in EEPROM and the unit is in standby mode, do we use a button to send the data?

The target is only 30 mm in diameter and could be passing at a speeds up to 10 m/s so the reading could be as quick as 3 ms.

Will the temperature sensor respond quickly enough?

The minimum time between readings would be approximately 150 ms.

That must be the time between sets of 10 readings?

The maximum distance would be 1 km. More likely 500 m. I was hoping that it would be received and sent to a PC. The PC would then display an alarm if any of the targets are overheating. I don't have a program to do this yet.

The wireless module that I have experience with that has that sort of range (claimed, unobstructed line of sight) is the APC220 radio. I have read of the XBee radios that might have that sort of range. Long range wireless is not a area where I have much expertise.

I can help to get to the reading, storing and sending of the data to the serial monitor via serial. From there adding wireless should be pretty easy once a wireless method is chosen. A simple Processing Processing.org/ program could read the serial data and do pretty much what ever you need with the data.

groundfungus:
Writing to 10 float values to EEPROM is no problem. Using a full up Uno is problematic when considering low power. The USB-serial subsystem, various LEDs, running at 16Mhz, etc consume power (around 50 mA, I think). A stand alone 328 running at 8Mhz can consume less than 1/4 the power. Then there is sleeping the processor (something new for me) to get current consumption into the micro amp range. low power

I don't want to have a bare bones board, so please don't worry too much about power consumption at this stage.

groundfungus:
Is button B is some sort of detector? What exactly?

I haven't got one at this stage. Perhaps some sort of ferro-resonant detector. This will detect the target and trigger the measurement.

groundfungus:
So the sampling of the temperature for each object triggered by the "button B detector" as well as sensing the arrival of the first object? So, button A is pressed, the unit enters measurement mode, the detector senses the first of ten, takes the reading, stores the reading, senses and reads 9 more objects and reads each of their temperatures, storing each reading then returns to standby?

There should be a gap of at least 60 s between groups of 10 targets. Ideally I would like the group of 10 temperatures to be saved to memory and then sent over the comms link. Once sent successfully then return to standby.

groundfungus:
Now the temperatures are stored in EEPROM and the unit is in standby mode, do we use a button to send the data?

I would prefer this to be sent automatically.

groundfungus:
Will the temperature sensor respond quickly enough?

I'm still researching fast non-temperature detectors. Specifically IR detectors.

groundfungus:
That must be the time between sets of 10 readings?

No. In the perfect scenario, the target will pass in pairs. Ideally the pattern of targets will be a gap of 150 ms between targets 1 and 2 and then a gap of approximately 1 s between 2 and 3. The a gap of 150 ms between 3 and 4. This pattern is repeated for the group of 10.

groundfungus:
The wireless module that I have experience with that has that sort of range (claimed, unobstructed line of sight) is the APC220 radio. I have read of the XBee radios that might have that sort of range. Long range wireless is not a area where I have much expertise.

I would be happy with a wifi link for the moment, just to prove the wireless communications.

groundfungus:
I can help to get to the reading, storing and sending of the data to the serial monitor via serial. From there adding wireless should be pretty easy once a wireless method is chosen. A simple Processing Processing.org/ program could read the serial data and do pretty much what ever you need with the data.

Thanks very much, I will have a look at this.

Since I don't have the actual hardware to work with I must simulate the hardware. So I think the way to go forward is to go back to using the button B to sim the detector and the use temp sensor that I have. Since the reading of the button and temperature are in functions, those functions can be replaced in the final code with functions that use the actual hardware. That is the beauty of breaking the program into functions.

I can write the program to send the data via serial to the serial monitor, a Processing app or another app that accepts data from the serial port. Inserting the code for a wireless module can be done when the communication method is finalized. WIFI and networking is beyond my experience. Maybe someone else can help there.

Attached is the new Arduino sketch and a Processing sketch to receive and view the data. You don't need the Processing sketch if you just want to view the sketch output in serial monitor. In the Processing sketch, you will need to set the serial port to the port the Arduino is connected to. I changed the baud rate in the Arduino sketch to 115200, you will need to make sure serial monitor has a matching baud rate set.

The Arduino sketch:

initial state is standby
on button A enter measure mode
on button B save one sample to ram (simulates a detector)
after numMeasurements (default 10) samples transfer data from ram to EEPROM*
pull data from EEPROM and transmit via serial
return to standby mode

*I found that saving a data point to EEPROM takes longer than your 3mS minimum time so I save to ram while reading and transfer to EEPROM after readings taken.

Right now there is no way to abort while in measurement mode. The only way out is to get 10 readings. Also, no way to download EEPROM manually.

ten temps.zip (4.01 KB)

Thanks very much Groundfungus. I'll have a chance to play with this over the weekend and I'll let you know how I get on.

Good luck. Any questions, don't hesitate to ask. You may PM if you wish.

The OP has deleted his responses on this thread and now asked for it to be deleted.
Well, no.

It is extremely discourteous to ask a question, get replies, and then when everything is sorted, try to delete the question. People have taken the trouble to reply to you, and others in the future may get help from this thread. Please don't do that.

If you want to just get private help, pay someone.