Summary
In this series of articles I have been implementing a one-wire sensor library to work with PSoC 6. In this article I will test the library by reading the temperature from the DS18B20 sensor.
Article |
---|
PSoC 6 SDK OneWire Bus (Part 1) : Build Basic Project |
PSoC 6 SDK OneWire Bus (Part 2) : Implement Read & Write |
PSoC 6 SDK OneWire Bus (Part 3) : Remove Busy Wait & Debug |
PSoC 6 SDK OneWire Bus (Part 4): But, Can it Read the Temperature? |
PSoC 6 SDK OneWire Bus (Part 5): Round out the OWB Driver |
Story
After three articles crawling through one-wire documents and firmware we are down to the real question. Will it actually read the temperature? Each device on a one-wire bus is addressed by a unique 64-bit value which is programmed at the factory. Before you can talk to a device you need to read the rom value. The question is how do you find the ROM value when you have multiple devices connected on the bus? There are two ways
- Follow a rather complicated discovery process (next article)
- If there is only 1 device on the bus you can follow a short cut.
Well, lets start with the simple method.
Read ROM
The data sheet is pretty clear about how to read the ROM code when you only have one device. Basically, you send a 0x33, then you read 8 bytes. Here is a clip from the data sheet.
I will add a command to my ntshell command line. The command is “readrom” it will
- Send the reset
- Wait 1MS (I don’t think you have to do this, but this was a bug work around)
- Send the 0x33
- Then read 8 bytes.
- And print out the result (lines
OneWireBus_ROMCode rom; static int usrcmd_readrom(int argc, char **argv) { owb_ret_t rval; printf("Sending reset\n"); bool result; rval = owb_reset(&bus,&result); if(rval != OWB_STATUS_OK) { printf("Reset failed\n"); return 0; } CyDelay(1); printf("Sending 0x33\n"); rval = owb_write_byte(&bus,0x33); if(rval != OWB_STATUS_OK) { printf("Write 0x33 failed\n"); return 0; } // read 64-bit rom printf("Reading 8 bytes\n"); rval = owb_read_bytes(&bus,rom.romAddr,8); if(rval != OWB_STATUS_OK) { printf("read 8 bytes failed\n"); return 0; } // printf("Rom = "); for(int i=0;i<8;i++) { printf("%02X ",rom.romAddr[i]); } printf("\n"); return 0; }
When I test it, things seem to be working.
Read Temperature
Now that we know the ROM Code, which is used as the address, how do we get the temperature. To do this you should follow this procedure.
- Do a Match ROM
- Send the ROM address
- Send a Convert Temperature
- Wait for the right amount of time
- Send a Read Scratch Pad
- Read 9 Bytes
- Convert the values
The Match ROM command 0x55 + the ROM code selects your device to be acted on.
When you send a convert T 0x44 your device will start the internal process of reading the temperature and storing it in the scratch pad. The amount of time this take depends on what resolution you have configured.
The scratchpad is a 9-byte register inside of the chip which contains the most recently read temperature plus some settings.
To read the scratchpad you need to send a 0xBE, then read 9-bytes. Notice that the 9th byte is a CRC for the first 8 bytes, if you are concerned you can follow the CRC procedure documented in the datasheet to calculate a CRC to verify a match. For this example, lets skip that.
In order to convert the temperature you need to know the resolution. Bit-6 and Bit-5 of the configuration register tells you this. This is a writable register so you can change the resolution which you might do to speed up the reading time.
Here is the whole code together as a new command.
static int usrcmd_readtemp(int argc, char **argv) { uint8_t scratchpad[9]; bool result; // send reset // send match rom 0x55 // send rom address // send trigger 0x44 // delay 1 second // send reset // send match rom 0x55 // send read scratchpad BEh // read 9 bytes of scratch pad owb_reset(&bus,&result); owb_write_byte(&bus,0x55); owb_write_bytes(&bus,rom.romAddr,8); owb_write_byte(&bus,0x44); vTaskDelay(1000); owb_reset(&bus,&result); owb_write_byte(&bus,0x55); owb_write_bytes(&bus,rom.romAddr,8); owb_write_byte(&bus,0xbe); owb_read_bytes(&bus,scratchpad,9); printf("Scratchpad ="); for(int i=0;i<9;i++) { printf("%02X ",scratchpad[i]); } printf("\n"); int16_t tempbits = scratchpad[0] | (scratchpad[1] << 8); uint32_t resolution=2^12; float temperature=0.0; switch(scratchpad[5] >>5 & 0x03) { case 0: resolution = 2^9; break; case 1: resolution = 2^10; break; case 2: resolution = 2^11; break; case 3: resolution = 2^12; break; } temperature = (float)tempbits / (float)resolution; printf("Temperature = %f\n",temperature); return 0; }
Now I build and program the development kit to setup the test. The first step is to read the ROM with the command line “readrom”. Then I tell it to try to read the temperature. You can see the values in the scratch pad, plus my conversion to celsius. Since I am in Kentucky I probably should have done Fahrenheit … oh well. 28.35C is 83.3F my office is pretty hot today.
No comment yet, add your voice below!