Skip to content
This repository was archived by the owner on Mar 17, 2020. It is now read-only.

Commit 5dd9e52

Browse files
committed
Add initial code for supporting a better temperature sensor (AM2302)
1 parent e089263 commit 5dd9e52

File tree

2 files changed

+164
-2
lines changed

2 files changed

+164
-2
lines changed

zephyr/x86_app/prj.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ CONFIG_PWM=y
1313
CONFIG_PWM_QMSI_NUM_PORTS=3
1414
CONFIG_PWM_DW=n
1515
CONFIG_PWM_QMSI=y
16+
CONFIG_GPIO=y
1617
CONFIG_ARC_INIT=y
1718
CONFIG_IPM=y
1819
CONFIG_IPM_QUARK_SE=y

zephyr/x86_app/src/service.c

Lines changed: 163 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
#include <bluetooth/uuid.h>
3939
#include <bluetooth/gatt.h>
4040

41+
#include <gpio.h>
42+
#include <sys_clock.h>
43+
4144
QUARK_SE_IPM_DEFINE(temperature_ipm, 0, QUARK_SE_IPM_INBOUND);
4245

4346
#define BT_UUID_WEBBT BT_UUID_DECLARE_16(0xfc00)
@@ -53,7 +56,7 @@ static uint8_t simulate_blvl;
5356
static uint8_t temperature = 20;
5457
static uint8_t rgb[3] = {0xff, 0x00, 0x00}; // red
5558

56-
struct device *pwm, *tmp36;
59+
struct device *pwm, *tmp36, *tmp2302;
5760
#define IO3_RED 0
5861
#define IO5_GREEN 1
5962
#define IO6_BLUE 2
@@ -65,6 +68,22 @@ struct device *pwm, *tmp36;
6568
#define PERIOD 64000
6669
#define MAX(a,b) (((a)>(b))?(a):(b))
6770

71+
#if defined(CONFIG_GPIO_DW_0)
72+
#define GPIO_DRV_NAME CONFIG_GPIO_DW_0_NAME
73+
#elif defined(CONFIG_GPIO_QMSI_0)
74+
#define GPIO_DRV_NAME CONFIG_GPIO_QMSI_0_NAME
75+
#elif defined(CONFIG_GPIO_ATMEL_SAM3)
76+
#define GPIO_DRV_NAME CONFIG_GPIO_ATMEL_SAM3_PORTB_DEV_NAME
77+
#elif
78+
#define GPIO_DRV_NAME "GPIO_0"
79+
#endif
80+
81+
#define IO8_AM2302 16
82+
83+
uint32_t start_time;
84+
uint32_t stop_time;
85+
uint32_t cycles_spent;
86+
6887
void pwm_write(void)
6988
{
7089
uint32_t r_on, g_on, b_on;
@@ -160,9 +179,145 @@ void temperature_ipm_callback(void *context, uint32_t id, volatile void *data)
160179
bt_gatt_notify(conn, &attrs[2], &temperature, sizeof(temperature));
161180
}
162181

182+
uint32_t measure_signal(uint32_t signal)
183+
{
184+
uint32_t count = 1;
185+
186+
uint32_t readValue;
187+
188+
start_time = sys_cycle_get_32();
189+
190+
do {
191+
gpio_pin_read(tmp2302, IO8_AM2302, &readValue);
192+
if (count++ > 255) return -1;
193+
} while (readValue == signal);
194+
195+
stop_time = sys_cycle_get_32();
196+
197+
cycles_spent = stop_time - start_time;
198+
return SYS_CLOCK_HW_CYCLES_TO_NS(cycles_spent) / 1000; // Microseconds
199+
}
200+
201+
int verifyResponse(uint32_t response)
202+
{
203+
if (response >= 75 && response <= 85)
204+
return 1;
205+
return -1;
206+
}
207+
208+
int verifyLowSignal(uint32_t low)
209+
{
210+
if (low >= 48 && low <= 55)
211+
return 1;
212+
return -1;
213+
}
214+
215+
int checkHighSignal(uint32_t high)
216+
{
217+
if (high >= 68 && high <= 75)
218+
return 1;
219+
if (high >= 22 && high <= 30)
220+
return 0;
221+
return -1;
222+
}
223+
224+
void read_am2302_tmp()
225+
{
226+
uint32_t cycles[80];
227+
228+
gpio_pin_configure(tmp2302, IO8_AM2302, (GPIO_DIR_OUT));
229+
gpio_pin_write(tmp2302, IO8_AM2302, 1);
230+
task_sleep(USEC(1000));
231+
232+
// STEP 1+2
233+
234+
// We set MCU to output.
235+
// Due to previous pullup, it should always be high.
236+
237+
// We signal the AM2302 to wake up, by signaling
238+
// low for min 800us, but typically 1ms. (max 20ms).
239+
gpio_pin_write(tmp2302, IO8_AM2302, 0);
240+
task_sleep(USEC(1000));
241+
242+
// End the start signal by setting data line high for 40 microseconds.
243+
gpio_pin_write(tmp2302, IO8_AM2302, 1);
244+
task_sleep(USEC(40));
245+
246+
// Then set MCU to input and release the bus
247+
// Due to pullup, it will go high and it will take
248+
// at least 20us, though typically 30ns and
249+
// max 200ns for the AM2302 to signal low.
250+
gpio_pin_configure(tmp2302, IO8_AM2302, (GPIO_DIR_IN));
251+
task_sleep(USEC(10));
252+
253+
// Signal from AM2302 that it is ready to send data.
254+
255+
uint32_t time;
256+
257+
time = measure_signal(0);
258+
if (verifyResponse(time) < 0)
259+
printk("Response low time not within limits: %d\n", time);
260+
time = measure_signal(1);
261+
if (verifyResponse(time) < 0)
262+
printk("Response high time not within limits: %d\n", time);
263+
264+
// Read data.
265+
for (int i = 0; i < 80; i += 2) {
266+
cycles[i] = measure_signal(0);
267+
cycles[i+1] = measure_signal(1);
268+
}
269+
270+
// -- Timing critical code is now over. --
271+
272+
uint8_t dataset[5];
273+
274+
// Each data set is 5 bytes (5 * 8 = 40)
275+
for (int i = 0; i < 40; ++i) {
276+
uint32_t low = cycles[2*i];
277+
uint32_t high = cycles[2*i+1];
278+
279+
dataset[i/8] <<= 1; // Move existing value one bit.
280+
281+
int lowstate = verifyLowSignal(low);
282+
int highstate = checkHighSignal(high);
283+
284+
if (highstate == 1)
285+
dataset[i/8] |= 1;
286+
287+
if (lowstate < 0 || highstate < 0) printk("X: "); else printk("%d: ", highstate);
288+
printk("low"); if (lowstate < 0) printk("*"); printk("\t: %d\t/\t", low);
289+
printk("high"); if (highstate < 0) printk("*"); printk("\t: %d\n", high);
290+
if ((i + 1) % 8 == 0) printk("\n");
291+
}
292+
293+
// Debugging:
294+
for (int j = 0; j < 5; j++){
295+
printk("%d ", dataset[j]);
296+
}
297+
printk("\n");
298+
299+
// Checksum check:
300+
if (dataset[4] != ((dataset[0] + dataset[1] + dataset[2] + dataset[3]) & 0xFF)) {
301+
printk("Checksum failed!\n");
302+
}
303+
304+
float humidity = (float) (dataset[0] << 8 | dataset[1]) / 10.0;
305+
printk("Humidity: %f \n", humidity);
306+
float temperature;
307+
308+
int neg = dataset[2] & 0x80; // higtest bit only.
309+
dataset[2] &= 0x7F; // Remove highest bit.
310+
311+
temperature = (float) (dataset[2] << 8 | dataset[3]) / 10.0;
312+
if (neg > 0)
313+
temperature *= -1;
314+
315+
printk("Temperature: %f \n", temperature);
316+
}
317+
163318
void service_init(struct bt_conn *conn)
164319
{
165-
if ((pwm = device_get_binding("PWM")) == NULL)
320+
if ((pwm = device_get_binding("PWM_0")) == NULL)
166321
printk("device_get_binding: failed for PWM\n");
167322
else {
168323
pwm_write();
@@ -176,4 +331,10 @@ void service_init(struct bt_conn *conn)
176331
ipm_set_enabled(ipm, 1);
177332

178333
bt_gatt_register(attrs, ARRAY_SIZE(attrs));
334+
335+
if((tmp2302 = device_get_binding(GPIO_DRV_NAME)) == NULL)
336+
printk("device_get_binding: failed for TMP2302\n");
337+
else {
338+
read_am2302_tmp();
339+
}
179340
}

0 commit comments

Comments
 (0)