2017-07-05

RF Temperature Sensor

This is a sensor that measures the temperature and transmits it over 433.92MHz radio. It uses the protocol for the weather1 sensor in pimatic/rfcontroljs [1].

Components

Arduino Pro Mini 5V [2]
TX433N Transmitter [3]
KTY84/150 Temperature Sensor [4]
1 kOhm Resistor
Coil Loaded Antenna [5]
9V Battery Connector

Assembly

The Arduino is the backbone of the construction. Connect the battery connector to RAW and GND. The KTY84 and the resistor forms a voltage divider. KTY84 connects to GND and Analog 3. The resistor connects to Analog 3 and VCC. TX433N is powered by VCC and GND on the Arduino. Connect Data to Digital 2. Connect the coil loaded antenna to Ant.

Configuration

The sensor is configured with messages sent on the serial port (115200 bps). The following values can be set.

0: Exact resistance of the 1 kOhm Resistor
1: Exact resistance of KTY84 at zero degrees Celsius
2: Id 0-255 (weather1)
3: Channel 1-4 (weather1)
4: Measurement Interval 0-32767 (ms)

Example: To set the KTY84 resistance to 509 Ohm, send the following message, ending with newline.

1:509

Calibration

To calibrate the sensor, first measure the resistance of the 1 kOhm resistor and write the value to config 0. Then adjust config 1 until the measured temperature matches the value of a reference temperature. 

References

[1] https://github.com/pimatic/rfcontroljs
[2] https://www.arduino.cc/en/Main/ArduinoBoardProMini
[3] https://www.velleman.eu/products/view/?id=350619
[4] http://www.nxp.com/docs/en/data-sheet/KTY84_SER.pdf
[5] http://www.instructables.com/id/433-MHz-Coil-loaded-antenna

Source Code

/*
  Copyright (C) 2017  Marcus Andersson

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see .
*/

#include "EEPROM.h"

// Digital
int ledPin = 13;
int txPin = 2;

// Analog
int thermoPin = 3;

// Pulse period time, 10 microsecond steps
#define PT 48

// Number of config values
#define NCONFIG 5

// EEPROM stored configuration data
struct Config {
  int data[NCONFIG];
};
Config config;

#define BUFLEN 100
byte packet[BUFLEN];
byte length = 0;

void printConfig() {
  for (int i = 0; i < NCONFIG; i++) {
    Serial.print(i);
    Serial.print(": ");
    Serial.println(config.data[i]);
  }
}

void setConfig(int i, int val) {
  config.data[i] = val;
  EEPROM.put(0, config);
}

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(txPin, OUTPUT);
  Serial.begin(115200);
  EEPROM.get(0, config);
  printConfig();
}

void send(int temp, byte id, byte ch) {
  int i, j;
  unsigned long t0;
  unsigned long periods;
  byte data[36] = {
    0, 1, 0, 1,
    1, 1, 0, 1, 0, 0, 0, 0, // id
    1, 1, // batt
    0, 1, // channel
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // temp
    0, 0, 0, 0, 0, 0, 0, 0 // hum
  }; 
 
  // Write id
  for (i = 0; i < 8; i++) {
    data[4+i] = (id >> (7-i)) & 1;
  }
 
  // Write channel
  data[14] = ((ch-1) >> 1) & 1;
  data[15] = ((ch-1) >> 0) & 1;
 
  // Write temp
  data[16] = (temp < 0) ? 1 : 0;
  for (i = 1; i < 12; i++) {
    data[16+i] = (temp >> (11-i)) & 1;
  }
 
  digitalWrite(ledPin, HIGH);   // sets the LED on

  periods = 0;
  t0 = micros();
 
  digitalWrite(txPin, HIGH); periods += 8;
  delayMicroseconds(max(10000, t0 + periods*PT - micros()));
  digitalWrite(txPin, LOW); periods += 230;
  delayMicroseconds(max(10000, t0 + periods*PT - micros()));

  for (j = 0; j < 4; j++) {
    for (i = 0; i < 36; i++) {
      digitalWrite(txPin, HIGH); periods += 8;
      delayMicroseconds(max(10000, t0 + periods*PT - micros()));
      digitalWrite(txPin, LOW); periods += 4*10 + 4*11*data[i];
      delayMicroseconds(max(10000, t0 + periods*PT - micros()));
    }

    digitalWrite(txPin, HIGH); periods += 8;
    delayMicroseconds(max(10000, t0 + periods*PT - micros()));
    digitalWrite(txPin, LOW); periods += 230;
    delayMicroseconds(max(10000, t0 + periods*PT - micros()));
  }
  digitalWrite(ledPin, LOW);    // sets the LED off
}

void loop()
{
  static unsigned long sendTime = millis() - config.data[4];
 
  if (millis() - sendTime > config.data[4]) {
    long r0 = config.data[0];
    long r1 = config.data[1];
    long id = config.data[2];
    long ch = config.data[3];
    long s = analogRead(thermoPin);
    long r = r0*s/(1023-s);
    int t = (r-r1)*2;
   
    sendTime += config.data[4];
    send(t, id, ch);
   
    Serial.print(s);
    Serial.print(" ");
    Serial.println(t);
  }

  while (Serial.available() > 0) {
    int d = Serial.read();
    packet[length++] = d;
    if (d == 10 || length >= BUFLEN) {
      int p = 0;
      int i = packet[p++] - '0';
      if (i >= 0 && i < NCONFIG) {
        int v = 0;
        int d = packet[p++];
        d = packet[p++];
        while (d >= '0' && d <= '9') {
          v = v*10 + d - '0';
          d = packet[p++];
        }
        setConfig(i, v);
        printConfig();
      }
      length = 0;
    }
  } 
}


No comments: