Paparazzi UAS  v5.15_devel-111-g8fb4629
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
humid_sht.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2014 The Paparazzi team
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
31 #include "std.h"
32 #include "mcu_periph/gpio.h"
33 #include "mcu_periph/uart.h"
34 #include "pprzlink/messages.h"
36 #include "humid_sht.h"
37 
38 // sd-log
39 #if SHT_SDLOG
41 #include "subsystems/gps.h"
42 bool log_sht_started;
43 #endif
44 
45 //#include "led.h"
46 
47 #define noACK 0
48 #define ACK 1
49 #define TEMP 0
50 #define HUMI 1
51 
52 //adr command r/w
53 //000 0011 0
54 #define STATUS_REG_W 0x06
55 //000 0011 1
56 #define STATUS_REG_R 0x07
57 //000 0001 1
58 #define MEASURE_TEMP 0x03
59 //000 0010 1
60 #define MEASURE_HUMI 0x05
61 //000 1111 0
62 #define RESET 0x1e
63 
64 
65 #define SHT_IDLE 0
66 #define SHT_MEASURING_HUMID 1
67 #define SHT_MEASURING_TEMP 2
68 
69 #if !defined SHT_DAT_GPIO || !defined SHT_SCK_GPIO
70 #error You need to define SHT_DAT_GPIO and SHT_SCK_GPIO
71 #endif
72 
74 #define DATA_SET gpio_setup_input(SHT_DAT_GPIO)
75 #define DATA_CLR gpio_setup_output(SHT_DAT_GPIO)
77 #define DATA_IN gpio_get(SHT_DAT_GPIO)
79 
81 #define SCK_SET gpio_set(SHT_SCK_GPIO)
82 #define SCK_CLR gpio_clear(SHT_SCK_GPIO)
84 
85 
90 
93 void s_transstart(void);
94 void s_connectionreset(void);
95 uint8_t s_read_statusreg(uint8_t *p_value, uint8_t *p_checksum);
97 uint8_t s_measure(uint16_t *p_value, uint8_t *p_checksum, uint8_t mode);
99 uint8_t s_read_measure(uint16_t *p_value, uint8_t *p_checksum);
100 void calc_sht(uint16_t hum, uint16_t tem, float *fhum , float *ftem);
102 
103 
105 {
106  uint8_t i, error = 0;
107 
108  for (i = 0x80; i > 0; i /= 2) { //shift bit for masking
109  if (i & value) { DATA_SET; } //masking value with i , write to SENSI-BUS
110  else { DATA_CLR; }
111  SCK_SET; //clk for SENSI-BUS
112  SCK_SET; SCK_SET; SCK_SET; //pulswith approx. 5 us
113  // _nop_();_nop_();_nop_(); //pulswith approx. 5 us
114  SCK_CLR;
115  }
116  DATA_SET; //release DATA-line
117  SCK_SET; //clk #9 for ack
118  error = DATA_IN; //check ack (DATA will be pulled down by SHT11)
119  SCK_CLR;
120 
121  return error; //error=1 in case of no acknowledge
122 }
123 
125 {
126  uint8_t i, val = 0;
127 
128  DATA_SET; //release DATA-line
129  for (i = 0x80; i > 0; i /= 2) { //shift bit for masking
130  SCK_SET; //clk for SENSI-BUS
131  if (DATA_IN) { val = (val | i); } //read bit
132  SCK_CLR;
133  }
134 
135  if (ack) { DATA_CLR; } //in case of "ack==1" pull down DATA-Line
136  SCK_SET; //clk #9 for ack
137  SCK_SET; SCK_SET; SCK_SET; //pulswith approx. 5 us
138  // _nop_();_nop_();_nop_(); //pulswith approx. 5 us
139  SCK_CLR;
140  DATA_SET; //release DATA-line
141  return val;
142 }
143 
144 void s_transstart(void)
145 {
146  // generates a transmission start
147  // _____ ________
148  // DATA: |_______|
149  // ___ ___
150  // SCK : ___| |___| |______
151 
152  DATA_SET; SCK_CLR; //Initial state
153  SCK_CLR;// _nop_();
154  SCK_SET;
155  SCK_SET;// _nop_();
156  DATA_CLR;
157  DATA_CLR;// _nop_();
158  SCK_CLR;
159  SCK_CLR; SCK_CLR; SCK_CLR; // _nop_();_nop_();_nop_();
160  SCK_SET;
161  SCK_SET;// _nop_();
162  DATA_SET;
163  DATA_SET;// _nop_();
164  SCK_CLR;
165 }
166 
168 {
169  // communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
170  // _____________________________________________________ ________
171  // DATA: |_______|
172  // _ _ _ _ _ _ _ _ _ ___ ___
173  // SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |______
174 
175  uint8_t i;
176 
177  DATA_SET; SCK_CLR; //Initial state
178  for (i = 0; i < 9; i++) { //9 SCK cycles
179  SCK_SET;
180  SCK_CLR;
181  }
182  s_transstart(); //transmission start
183 }
184 
185 uint8_t s_read_statusreg(uint8_t *p_value, uint8_t *p_checksum)
186 {
187  // reads the status register with checksum (8-bit)
188  uint8_t error = 0;
189 
190  s_transstart(); //transmission start
191  error = s_write_byte(STATUS_REG_R); //send command to sensor
192  *p_value = s_read_byte(ACK); //read status register (8-bit)
193  *p_checksum = s_read_byte(noACK); //read checksum (8-bit)
194  return error; //error=1 in case of no response form the sensor
195 }
196 
198 {
199  // writes the status register with checksum (8-bit)
200  uint8_t error = 0;
201 
202  s_transstart(); //transmission start
203  error += s_write_byte(STATUS_REG_W); //send command to sensor
204  error += s_write_byte(*p_value); //send value of status register
205  return error; //error>=1 in case of no response form the sensor
206 }
207 
208 uint8_t s_measure(uint16_t *p_value, uint8_t *p_checksum, uint8_t mode)
209 {
210  // makes a measurement (humidity/temperature) with checksum
211  uint8_t error = 0;
212  uint32_t i;
213 
214  s_transstart(); //transmission start
215  switch (mode) { //send command to sensor
216  case TEMP : error += s_write_byte(MEASURE_TEMP); break;
217  case HUMI : error += s_write_byte(MEASURE_HUMI); break;
218  default : break;
219  }
220  for (i = 0; i < 6665535; i++) if (DATA_IN == 0) { break; } //wait until sensor has finished the measurement
221  if (DATA_IN) { error += 1; } // or timeout (~2 sec.) is reached
222  *(p_value) = s_read_byte(ACK) << 8; //read the first byte (MSB)
223  *(p_value) |= s_read_byte(ACK); //read the second byte (LSB)
224  *p_checksum = s_read_byte(noACK); //read checksum
225 
226  return error;
227 }
228 
230 {
231  // makes a measurement (humidity/temperature) with checksum
232  uint8_t error = 0;
233 
234  s_transstart(); //transmission start
235  switch (mode) { //send command to sensor
236  case TEMP : error += s_write_byte(MEASURE_TEMP); break;
237  case HUMI : error += s_write_byte(MEASURE_HUMI); break;
238  default : break;
239  }
240 
241  return error;
242 }
243 
244 uint8_t s_read_measure(uint16_t *p_value, uint8_t *p_checksum)
245 {
246  // reads a measurement (humidity/temperature) with checksum
247  uint8_t error = 0;
248 
249  if (DATA_IN) { error += 1; } //still busy?
250  *(p_value) = s_read_byte(ACK) << 8; //read the first byte (MSB)
251  *(p_value) |= s_read_byte(ACK); //read the second byte (LSB)
252  *p_checksum = s_read_byte(noACK); //read checksum
253 
254  return error;
255 }
256 
257 void calc_sht(uint16_t hum, uint16_t tem, float *fhum , float *ftem)
258 {
259  // calculates temperature [ C] and humidity [%RH]
260  // input : humi [Ticks] (12 bit)
261  // temp [Ticks] (14 bit)
262  // output: humi [%RH]
263  // temp [ C]
264 
265  const float C1 = -4.0; // for 12 Bit
266  const float C2 = 0.0405; // for 12 Bit
267  const float C3 = -0.0000028; // for 12 Bit
268  const float T1 = 0.01; // for 14 Bit @ 5V
269  const float T2 = 0.00008; // for 14 Bit @ 5V
270  float rh; // rh: Humidity [Ticks] 12 Bit
271  float t; // t: Temperature [Ticks] 14 Bit
272  float rh_lin; // rh_lin: Humidity linear
273  float rh_true; // rh_true: Temperature compensated humidity
274  float t_C; // t_C : Temperature [ C]
275 
276  rh = (float)hum; //converts integer to float
277  t = (float)tem; //converts integer to float
278 
279  t_C = t * 0.01 - 39.66; //calc. Temperature from ticks to [°C] @ 3.5V
280  rh_lin = C3 * rh * rh + C2 * rh + C1; //calc. Humidity from ticks to [%RH]
281  rh_true = (t_C - 25) * (T1 + T2 * rh) + rh_lin; //calc. Temperature compensated humidity [%RH]
282  if (rh_true > 100) { rh_true = 100; } //cut if the value is outside of
283  if (rh_true < 0.1) { rh_true = 0.1; } //the physical possible range
284  *ftem = t_C; //return temperature [ C]
285  *fhum = rh_true; //return humidity[%RH]
286 }
287 
289 {
290  // resets the sensor by a softreset
291  uint8_t error = 0;
292 
293  s_connectionreset(); //reset communication
294  error += s_write_byte(RESET); //send RESET-command to sensor
295 
296  return error; //error=1 in case of no response form the sensor
297 }
298 
299 void humid_sht_init(void)
300 {
301  /* Configure DAT/SCL pin as GPIO */
302  gpio_setup_input(SHT_DAT_GPIO);
303  gpio_setup_output(SHT_SCK_GPIO);
304  gpio_clear(SHT_SCK_GPIO);
305 
306 
307  humid_sht_available = false;
309 
310 #if SHT_SDLOG
311  log_sht_started = false;
312 #endif
313 
314 }
315 
317 {
318  uint8_t error = 0, checksum;
319 
320  if (humid_sht_status == SHT_IDLE) {
321  /* init humidity read */
325  } else if (humid_sht_status == SHT_MEASURING_HUMID) {
326  /* get data */
327  error += s_read_measure(&humidsht, &checksum);
328 
329  if (error != 0) {
331  s_start_measure(HUMI); //restart
332  //LED_TOGGLE(2);
333  } else {
334  error += s_start_measure(TEMP);
336  }
337  } else if (humid_sht_status == SHT_MEASURING_TEMP) {
338  /* get data */
339  error += s_read_measure(&tempsht, &checksum);
340 
341  if (error != 0) {
343  s_start_measure(TEMP); //restart
344  //LED_TOGGLE(2);
345  } else {
347  humid_sht_available = true;
351  DOWNLINK_SEND_SHT_STATUS(DefaultChannel, DefaultDevice, &humidsht, &tempsht, &fhumidsht, &ftempsht);
352  humid_sht_available = false;
353 
354 #if SHT_SDLOG
355  if (pprzLogFile != -1) {
356  if (!log_sht_started) {
357  sdLogWriteLog(pprzLogFile, "SHT75: Humid(pct) Temp(degC) GPS_fix TOW(ms) Week Lat(1e7deg) Lon(1e7deg) HMSL(mm) gspeed(cm/s) course(1e7deg) climb(cm/s)\n");
358  log_sht_started = true;
359  }
360  sdLogWriteLog(pprzLogFile, "sht75: %9.4f %9.4f %d %d %d %d %d %d %d %d %d\n",
362  gps.fix, gps.tow, gps.week,
365  }
366 #endif
367 
368  }
369  }
370 }
unsigned short uint16_t
Definition: types.h:16
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
void humid_sht_init(void)
Definition: humid_sht.c:299
bool humid_sht_available
Definition: humid_sht.c:88
#define SHT_MEASURING_HUMID
Definition: humid_sht.c:66
void humid_sht_periodic(void)
Definition: humid_sht.c:316
#define DATA_SET
set data pin to input
Definition: humid_sht.c:74
#define SHT_IDLE
Definition: humid_sht.c:65
static void gpio_clear(ioportid_t port, uint16_t pin)
Clear a gpio output to low level.
Definition: gpio_arch.h:108
uint16_t week
GPS week.
Definition: gps.h:108
Some architecture independent helper functions for GPIOs.
#define HUMI
Definition: humid_sht.c:50
#define DATA_CLR
set data pin to output
Definition: humid_sht.c:76
uint8_t s_write_byte(uint8_t value)
Definition: humid_sht.c:104
uint16_t humidsht
!SITL
Definition: humid_sht.c:86
int32_t z
Down.
void gpio_setup_output(ioportid_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as outputs.
Definition: gpio_arch.c:33
#define TEMP
Definition: humid_sht.c:49
uint8_t s_write_statusreg(uint8_t *p_value)
Definition: humid_sht.c:197
static uint8_t checksum
Definition: airspeed_uADC.c:60
uint8_t s_read_measure(uint16_t *p_value, uint8_t *p_checksum)
Definition: humid_sht.c:244
int32_t hmsl
height above mean sea level (MSL) in mm
Definition: gps.h:94
#define STATUS_REG_W
Definition: humid_sht.c:54
#define MEASURE_HUMI
Definition: humid_sht.c:60
uint8_t humid_sht_status
Definition: humid_sht.c:89
uint32_t tow
GPS time of week in ms.
Definition: gps.h:109
Device independent GPS code (interface)
uint16_t val[TCOUPLE_NB]
unsigned long uint32_t
Definition: types.h:18
#define SCK_SET
set clock pin to high
Definition: humid_sht.c:81
int32_t lon
in degrees*1e7
FileDes pprzLogFile
Definition: sdlog_chibios.c:85
#define STATUS_REG_R
Definition: humid_sht.c:56
#define MEASURE_TEMP
Definition: humid_sht.c:58
uint8_t s_read_byte(uint8_t ack)
Definition: humid_sht.c:124
uint8_t s_start_measure(uint8_t mode)
Definition: humid_sht.c:229
#define SHT_MEASURING_TEMP
Definition: humid_sht.c:67
uint8_t humid_sht_reset(void)
Definition: humid_sht.c:288
void s_transstart(void)
Definition: humid_sht.c:144
SHTxx sensor interface.
void calc_sht(uint16_t hum, uint16_t tem, float *fhum, float *ftem)
Definition: humid_sht.c:257
unsigned char uint8_t
Definition: types.h:14
int32_t course
GPS course over ground in rad*1e7, [0, 2*Pi]*1e7 (CW/north)
Definition: gps.h:99
static uint8_t mode
mode holds the current sonar mode mode = 0 used at high altitude, uses 16 wave patterns mode = 1 used...
Definition: sonar_bebop.c:69
uint8_t s_read_statusreg(uint8_t *p_value, uint8_t *p_checksum)
Definition: humid_sht.c:185
float ftempsht
Definition: humid_sht.c:87
#define SCK_CLR
set clock pin to low
Definition: humid_sht.c:83
uint16_t gspeed
norm of 2d ground speed in cm/s
Definition: gps.h:97
#define noACK
Definition: humid_sht.c:47
#define ACK
Definition: humid_sht.c:48
struct LlaCoor_i lla_pos
position in LLA (lat,lon: deg*1e7; alt: mm over ellipsoid)
Definition: gps.h:92
void s_connectionreset(void)
Definition: humid_sht.c:167
int32_t lat
in degrees*1e7
void gpio_setup_input(ioportid_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as inputs.
Definition: gpio_arch.c:40
uint8_t fix
status of fix
Definition: gps.h:107
uint8_t s_measure(uint16_t *p_value, uint8_t *p_checksum, uint8_t mode)
Definition: humid_sht.c:208
struct NedCoor_i ned_vel
speed NED in cm/s
Definition: gps.h:96
float fhumidsht
Definition: humid_sht.c:87
#define DATA_IN
get data pin
Definition: humid_sht.c:78
uint16_t tempsht
Definition: humid_sht.c:86
struct GpsState gps
global GPS state
Definition: gps.c:69
#define RESET
Definition: humid_sht.c:62