I am trying to sense the temperature using the LM70 temperature sensor with an Arduino Mega. As you can see in the Datasheet, it uses the SPI protocol. I have made the following connections (VSSOP-8 Package):
- SI/O pin --> Pin 50 Arduino Mega.
- SC pin --> Pin 52 Arduino Mega.
- CS pin --> Pin 53 Arduino Mega.
- V+ pin --> 3.3V Arduino Mega.
- GND pin --> GND Arduino Mega.
My code does not work (it does not print the right temperature), and I think it can be for two reasons:
- I am not reading correctly the information from the sensor. It sends 16 bits, from which the 11 first bits store the data for the temperature.
- I am not calculating the temperature in the right way.
This is my code:
// the sensor communicates using SPI, so include the library:
#include <SPI.h>
void setup() {
pinMode(51,OUTPUT); //MOSI
pinMode(50,INPUT); //MISO
pinMode(52,OUTPUT); //CLOCK PIN
digitalWrite(53,HIGH); //slave select stays high. When we set this to low, the sensor will start to send data.
SPI.begin();
Serial.begin(9600);
//time to set up
delay(500);
}
void loop() {
//enable Slave
digitalWrite(A0,LOW); //Enable communication with slave
delay(500); //wait for conversion
int val = SPI.transfer(0x00); // read from sensor
Serial.println(val); //display reading on serial monitor
int temperature = val * 0.25;
Serial.println(temperature); //display temperature on serial monitor
//disable Slave
digitalWrite(53,HIGH); //set to High again
}
Please, if you see something wrong in my code, let me know. Thank you in advance.
2 Answers 2
There are several things that are not doing correctly. This is not a complete answer but to provide you some directions on how to get it right.
A0
is pin 54, it is notSS
which is pin 53;On how to use the SPI library properly, I would suggest that you read my blog on SPI, it will also help you to get the data out of data sheet that you need for SPI programming. Based on the timing diagram on the data sheet, you will need to configure the SPI as
SPI_MODE2
;LM70 SI/O pin is used as both MOSI and MISO, you will need to connect MOSI to SI/O via a 10k resistor, and connect SI/O direct to MISO, this information is available in the data sheet;
LM70's temperature data is in Two's complement format, To convert it, it needs a little bit work. It is then need to shift down/right using bitshift operator by 5 bits to get ride of the first 5-bits, before finally multiply by 0.25C as per data sheet.
int value = 0x4b1f; //value from SPI, temp = 125 degree C
int mask = 0x8000; // mask for MSB
int temp = (-(value & mask) + (value & ~mask)) >> 5;
Serial.print("Temp");
Serial.println(temp*.25);
Read all links that I provided to understand the subjects and give it a try. Good luck!
Your problem lies here:
int val = SPI.transfer(0x00); // read from sensor
Serial.println(val); //display reading on serial monitor
int temperature = val * 0.25;
And it's a twofold problem.
First:
int val = SPI.transfer(0x00);
That only reads the first 8 bits of the data. To get all 16 bits you have to do two transfers and then combine them together with bitshifting:
int bh = SPI.transfer(0x00);
int bl = SPI.transfer(0x00);
int val = (bh << 8) | bl;
That then gives you a value that is right-aligned. you then need to shift it to the left the right number of bits and "sign extend" it to keep it negative if needed. If you're not interested in the fractional part then it's as simple as:
val >>= 7;
if (val & 0x0100) {
val |= 0xFE00;
}
Now... what does that all mean? Well, assume it's currently 25°C. From the datasheet we can see that would give us a reading of 0000 1100 1001 1111
(note there is a typo in the datasheet saying that is 0b9f in hex when in fact it's 0c9f).
Let's do those operations - first the bit shift:
Dec Hex Bin
3231 0C9F 0000110010011111 >> 7
25 0019 0000000000011001
Then we look to see if bit 8 is set or not (bit 8 was the most significant bit). If it is then we OR it with bits 9-15 also set. This "sign extends" it.
Let's take a look at -25°C from the datasheet:
Dec Hex Bin
-3169 f39f 1111001110011111 >> 7 Shift right 7 bits
487 01e7 0000000111100111 & 0x0100 And with 8th bit
256 0100 0000000100000000 Result is not 0 so is true
"Or" the shifted value with 0xFE00:
487 01e7 0000000111100111 or
65024 fe00 1111111000000000 =わ
-ひく25 ffe7 1111111111100111
digitalWrite(A0,LOW)
-- Are you sure about that one?