Measure and store multiple temperature with Arduino

Arduino Temperature SensorFor a certain IoT design I had to understand how my box design impacts the temperature of the circuit and of my battery. To understand how it works in the real environment, I made a small circuit based on an Arduino Nano to get temperature with 6 different sensors and store it in a flash memory for later use.

This post describes the way to do this multi-temperature sensor platform. Code is under GPL.

Components and Circuit

The components are an Arduino Nano, it have up to 7 analog input so we can have up-to 7 temperature sensors.

To measure temperature, I’m using MCP9700A. It have 1-2°C of precision in the expected temperature range. They are analog sensor with a linear conversion formula from mV to °C. You have 1°C per 10mV with a 0°C equal to 500mV.

The data are stored in a flash memory, I’m using a CAT24M01 offering 128KB connected over I2C. Basically I2C use some of the analog pins on Arduino Nano. As I was expecting to use all of them I decided to use a SoftI2C library and modify CAT24M01 lib for using it instead of Wire lib. For this reason the I2C pins are D4 and D5.

Circuit is basically what you can see here :

Arduino temperature sensor circuit

Arduino temperature sensor circuit

Libraries

For having this solution working I’m using 3 public libraries:

  • CAT24M01 – modified to support soft I2C and fixed for being able to read something
  • SoftI2CMaster – modified to make it working
  • Low-Power – unmodified – use to preserve energy

All these library are bundled in the global repository.

Main Code

All the code can be found in the following github repository : https://github.com/disk91/TempCapture

It can be cloned in your Document/Arduino directory as it contains the library repository.

Let’s take a look to some of the strange things in it :

#define convert2decdeg(x) (((((x*v) / 1024)-500)/10))
void refreshTemps() {
  long v = readVcc();
  long  a;
  
  a = analogRead(A6);
  temps.t[0] = (uint8_t)convert2decdeg(a);
  delay(100);

This peace of code is used for reading temperature. It starts getting VCC value as the Analog2Digital Converter is returning a value of 1023 for VCC but VCC is unknow : it depends on the battery and vary form a power source to another.

Then for each of the ADC values it converts it into °C there is no decimal as the precision of the sensor is +/- 1°C we do not really care about deci-degrees.

Temperature are stored is a structure

typedef struct s_temp {
  uint16_t ts;      // sequence number
  uint8_t  t[6];    // Temperatures
} t_temp;

It contains 6 different temperatures read from the 6 different sensors. A sequence number is also stored. This one is reset every time the arduino resets.

The data are stored one after one in the flash. The last written address is stored in the first bloc of memory and read at Arduino bootup.

void initEprom() {
/* --- First time use only
 ev.readAdr = 0x8;
 ev.writeAdr = 0x8;
 EEPROM1.write(0,(uint8_t*)&ev,sizeof(ev));
*/

 EEPROM1.read(0,(uint8_t*)&ev,sizeof(ev));
 Serial.print("Current Read Address :"); Serial.println(ev.readAdr);
 Serial.print("Current Write Address :"); Serial.println(ev.writeAdr);
 
}

The first time you connect the flash, this zone will not be initialized so you have two ways for doing this : you can uncomment the  line above or you can type “f” in the console. this will do the same.

The frequency uses for capturing temperature is defined here :

#define LOOPCYCLE_MS  (300000L)

This is the number of MS between two measure (5min by default)

The main loop is containing the following stuff :

 do {
    if (Serial.available()) {
      char c = Serial.read();
      switch (c) {
        case 'd': // dump temp in flash
           dumpTemp();
           break;
        case 'f' : // flush temp in flash
           flushTemp();
           break; 
      }
    }
    // sleep au max 250MS ... wake up on UART interrupt 
    LowPower.idle(SLEEP_250MS, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, 
                SPI_OFF, USART0_ON, TWI_OFF);
    currentMillis += 250;
    
    // blink the led every 10 seconds
    l+=250;
    if ( l > 10000 && l <= 10250 ) {
      digitalWrite(LED,HIGH);
    } else if ( l > 10250 ) {
      digitalWrite(LED,LOW);
      l = 0;
    } 
    
  } while ( currentMillis < LOOPCYCLE_MS );

It looks for Serial command like ‘d’ to dump memory of ‘f’ to flush the memory. The loop makes a low power sleep unactivating all the hardware component but keeping Serial active to wakeup on serial reception.

The second part of this code make the Arduino LED blinking every 10 seconds for having a keepalive signal.

Get results

You can plug/unplug the TempCapture system it will keep you measure in the flash memory. So you can install the system in any environment, then (later) plug it to a laptop, run the arduino console and type ‘d’ in it ; the system will start printing the values:

0;20;21;20;21;20;201;20;20;21;20;21;21
...

The first raw is the sequence number (subject to restart at 0 sometime indicating you had an arduino reset) the next one are temperature in °C as they have been measured.

First is corresponding to A6 sensor, Last to A1 sensor.

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.