The following example shows you how to use Z-Wave 800 Multilevel sensor example running on BRD2603A/ZGM230S to read temperature from DS18B20 one-wire sensor.
1. Connect DS18B20 Vdd, GND, and DQ (add extra 4.7K pull-high to Vdd) to pin 20, 1, and 2(PB03) on EXP-header of BRD2603A.
2. Install USTIMER, Z-Wave Debug, and Z-Wave Debug Print in project software component to use microsecond delay API USTIMER_DelayIntSafe and DEBUGPRINT to output data to SSv5 console 1.
3. Add the following code into MultilevelSensor_interface_sensor.c
#include "em_gpio.h"
#include "ustimer.h" //For microsecond delay
#include "em_core_generic.h" //For critical section
//Use PB03 on BRD2603A
#define DS_GPIO_PORT 1 //gpioPortB
#define DS_GPIO_PIN 3
#define CMD_CONVERTTEMP 0x44
#define CMD_RSCRATCHPAD 0xbe
#define CMD_WSCRATCHPAD 0x4e
#define CMD_CPYSCRATCHPAD 0x48
#define CMD_RECEEPROM 0xb8
#define CMD_RPWRSUPPLY 0xb4
#define CMD_SEARCHROM 0xf0
#define CMD_READROM 0x33
#define CMD_MATCHROM 0x55
#define CMD_SKIPROM 0xcc
#define CMD_ALARMSEARCH 0xec
#define DECIMAL_STEPS_12BIT 625 //.0625
inline void pullLineLow() {
GPIO_PinModeSet(DS_GPIO_PORT, DS_GPIO_PIN, gpioModePushPull, 0);
}
inline void releaseLine() {
GPIO_PinModeSet(DS_GPIO_PORT, DS_GPIO_PIN, gpioModeInputPull, 1);
}
inline void delayUs(uint16_t us) {
USTIMER_DelayIntSafe(us);
}
inline uint32_t readLineState() {
return GPIO_PinInGet(DS_GPIO_PORT, DS_GPIO_PIN);
}
void writeBit(uint8_t bit){
//Pull line low for 1uS
pullLineLow();
delayUs(1);
//If we want to write 1, release the line (if not will keep low)
if(bit) {
releaseLine();
}
//Wait for a while and release the line
delayUs(20);
releaseLine();
delayUs(1);
}
uint8_t readBit(void){
uint8_t bit = 0;
//Pull line low for 1uS
pullLineLow();
delayUs(1);
//Release line and wait for a while
releaseLine();
delayUs(8);
//Read line value
if(readLineState()){
bit=1;
}
//Wait for a while to return read value
delayUs(40);
return bit;
}
uint8_t readByte(void){
uint8_t i = 8, n = 0;
while(i--){
//Shift one position right and store read value
n >>= 1;
n |= (readBit() << 7);
}
return n;
}
void writeByte(uint8_t b){
uint8_t i = 8;
while(i--){
//Write actual bit and shift one position right to make the next bit ready
writeBit(b & 1);
b >>= 1;
}
}
uint32_t reset(){
uint32_t i;
pullLineLow();
delayUs(300);
releaseLine();
delayUs(60);
i = readLineState(); //(0=OK, 1=ERROR)
delayUs(300);
return i;
}
/*
Returns temperature read from DS18B20
Reading is returned mutiplied by 10000 i.e.
for 23.4560 degrees the result will be 234560
*/
uint32_t ds18b20GetTemparature(){
USTIMER_Init();
//Enter cirtical section
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_CRITICAL();
//Reset, skip ROM and start temperature conversion
if(reset()) {
DPRINT("DS18B20 is not responding---reset temperature conversion\n");
return 0;
}
writeByte(CMD_SKIPROM);
writeByte(CMD_CONVERTTEMP);
//Wait until conversion is complete
uint16_t timeout = 0xFFFF;
while(!readBit() && timeout > 0) {
timeout--;
//Feed WDG to avoid WDG reboot.
zpal_feed_watchdog();
}
if(0 == timeout) {
DPRINT("DS18B20 temperature conversion has timed out\n");
return 0;
}
//Reset, skip ROM and send command to read Scratchpad
if(reset()) {
DPRINT("DS18B20 is not responding---reset Scratchpad\n");
return 0;
}
writeByte(CMD_SKIPROM);
writeByte(CMD_RSCRATCHPAD);
uint8_t scratchpad[2] = {0, 0};
//Read Scratchpad (only 2 first bytes)
scratchpad[0] = readByte();
scratchpad[1] = readByte();
//Exit critial section.
CORE_EXIT_CRITICAL();
USTIMER_DeInit();
int8_t digit = scratchpad[0] >> 4;
digit |= (scratchpad[1] & 0x7) << 4;
//Store decimal digits
uint16_t decimal = scratchpad[0] & 0xf;
decimal *= DECIMAL_STEPS_12BIT;
return digit * 10000 + decimal;
}
4. Use the following two lines to replace "MultilevelSensor_temperature_humidity_sensor_read(&rh_data, &temp_data);" in cc_multilevel_sensor_air_temperature_interface_read_value.
temp_data=ds18b20GetTemparature();
temp_data=(int32_t)(temp_data/10);
5. Build and run the firmware on BRD2603A to see the following temperature reading from DS18B20.
No comments:
Post a Comment