Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Siddesh Shinde
Published © MIT

Pumbaa, it is Gas!

Use a LPG detector to periodically monitor the gas level and send alerts using Amazon SNS to subscribed email ids.

BeginnerProtip950
Pumbaa, it is Gas!

Things used in this project

Hardware components

Marvell MW302 IoT Starter Kit
Marvell MW302 IoT Starter Kit
×1
SparkFun LPG Gas Sensor - MQ-6
×1
Jumper wires (generic)
Jumper wires (generic)
×1

Software apps and online services

AWS IoT
Amazon Web Services AWS IoT
AWS SNS
Amazon Web Services AWS SNS

Story

Read more

Schematics

Fritzing Diagram

Code

Application code

C/C++
This is the C file which reads the value from the LPG sensor and uploads it to AWS IoT.
I have modified the standard file found at https://github.com/marvell-iot/aws_starter_sdk/tree/master/sample_apps
/*
 *  Copyright (C) 2008-2015, Marvell International Ltd.
 *  All Rights Reserved.
 */

#include <wm_os.h>
#include <wmstdio.h>
#include <wmtime.h>
#include <wmsdk.h>
#include <led_indicator.h>
#include <board.h>
#include <mdev_gpio.h>
#include <push_button.h>
#include <aws_iot_mqtt_interface.h>
#include <aws_iot_shadow_interface.h>
#include <aws_utils.h>
#include <lowlevel_drivers.h>
#include <mdev_pinmux.h>
#include <mdev_adc.h>

/* configuration parameters */
#include <aws_iot_config.h>

#include "aws_starter_root_ca_cert.h"
/* ADC definitions */
#define SAMPLES	1
#define ADC_GAIN	ADC_GAIN_2
#define BIT_RESOLUTION_FACTOR 32768	/* For 16 bit resolution (2^15-1) */
#define VMAX_IN_mV	3300	/* Max input voltage in milliVolts */


/*-----------------------Global declarations----------------------*/


uint16_t buffer[SAMPLES];
mdev_t *adc_dev;

/* These hold each pushbutton's count, updated in the callback ISR */
static volatile uint32_t pushbutton_a_count;
static volatile uint32_t pushbutton_a_count_prev = -1;
static volatile uint32_t pushbutton_b_count;
static volatile uint32_t pushbutton_b_count_prev = -1;
static volatile uint32_t led_1_state;
static volatile uint32_t led_1_state_prev = -1;

static output_gpio_cfg_t led_1;
static MQTTClient_t mqtt_client;
static int is_demo_started;

/* Thread handle */
static os_thread_t aws_starter_thread;
/* Buffer to be used as stack */
static os_thread_stack_define(aws_starter_stack, 8 * 1024);
/* aws iot url */
static char url[128];

#define UAP_SSID                "aws_starter"
#define UAP_PASSPHRASE          "marvellwm"
#define AMAZON_ACTION_BUF_SIZE  100
#define VAR_LED_1_PROPERTY      "led"
#define VAR_BUTTON_A_PROPERTY   "pb"
#define VAR_LPG_VALUE           "lpg"
#define VAR_BUTTON_B_PROPERTY   "pb_lambda"
#define RESET_TO_FACTORY_TIMEOUT 10000
#define BUFSIZE                  128


/* callback function invoked on reset to factory */
static void device_reset_to_factory_cb()
{
	invoke_reset_to_factory();
}

/* board_button_2() is configured to perform reset to factory,
 * when pressed for more than 10 seconds.
 */
static void configure_reset_to_factory()
{
	input_gpio_cfg_t pushbutton_reset_to_factory = {
		.gpio = board_button_2(),
		.type = GPIO_ACTIVE_LOW
	};
	push_button_set_cb(pushbutton_reset_to_factory,
			   device_reset_to_factory_cb,
			   RESET_TO_FACTORY_TIMEOUT, 0, NULL);
}

/* callback function invoked when pushbutton_a is pressed */
static void pushbutton_cb_a()
{
	if (pushbutton_a_count_prev == pushbutton_a_count) {
		pushbutton_a_count++;
	}
}

/* callback function invoked when pushbutton_b is pressed */
static void pushbutton_cb_b()
{
	if (pushbutton_b_count_prev == pushbutton_b_count) {
		pushbutton_b_count++;
	}
}

static void configure_led_and_button()
{
	input_gpio_cfg_t pushbutton_a = {
		.gpio = board_button_1(),
		.type = GPIO_ACTIVE_LOW
	};
	input_gpio_cfg_t pushbutton_b = {
		.gpio = board_button_2(),
		.type = GPIO_ACTIVE_LOW
	};

	led_1 = board_led_1();

	push_button_set_cb(pushbutton_a,
			   pushbutton_cb_a,
			   100, 0, NULL);
	push_button_set_cb(pushbutton_b,
			   pushbutton_cb_b,
			   100, 0, NULL);
}

static char client_cert_buffer[AWS_PUB_CERT_SIZE];
static char private_key_buffer[AWS_PRIV_KEY_SIZE];
static char thing_name[126];

/* populate aws shadow configuration details */
static int aws_starter_load_configuration(ShadowParameters_t *sp)
{
	int ret = WM_SUCCESS;
	char region[16];
	memset(region, 0, sizeof(region));

	/* read configured thing name from psm */
	ret = read_aws_thing(thing_name);
	if (ret == WM_SUCCESS) {
		sp->pMyThingName = thing_name;
	} else {
		/* if not found in psm, take the default thing name */
		sp->pMyThingName = AWS_IOT_MY_THING_NAME;
	}
	sp->pMqttClientId = AWS_IOT_MQTT_CLIENT_ID;

	/* read configured region name from psm */
	ret = read_aws_region(region);
	if (ret == WM_SUCCESS) {
		snprintf(url, sizeof(url), "data.iot.%s.amazonaws.com",
			 region);
	} else {
		snprintf(url, sizeof(url), "data.iot.%s.amazonaws.com",
			 AWS_IOT_MY_REGION_NAME);
	}
	sp->pHost = url;
	sp->port = AWS_IOT_MQTT_PORT;
	sp->pRootCA = rootCA;

	/* read configured certificate from psm */
	ret = read_aws_certificate(client_cert_buffer);
	if (ret != WM_SUCCESS) {
		wmprintf("Failed to configure certificate. Returning!\r\n");
		return -WM_FAIL;
	}
	sp->pClientCRT = client_cert_buffer;

	/* read configured private key from psm */
	ret = read_aws_key(private_key_buffer);
	if (ret != WM_SUCCESS) {
		wmprintf("Failed to configure key. Returning!\r\n");
		return -WM_FAIL;
	}
	sp->pClientKey = private_key_buffer;

	return ret;
}

static void make_str(char *property, int val, char buff_out[], int buff_len)
{
	if (!buff_out)
		return;

	snprintf(buff_out, buff_len, "{\"state\": {\"reported\":{\"%s\":%d}}}",
		 property, val);
}

void shadow_update_status_cb(const char *pThingName, ShadowActions_t action,
			     Shadow_Ack_Status_t status,
			     const char *pReceivedJsonDocument,
			     void *pContextData) {

	if (status == SHADOW_ACK_TIMEOUT) {
		wmprintf("shadow publish state change timeout occured\r\n");
	} else if (status == SHADOW_ACK_REJECTED) {
		wmprintf("shadow publish state change rejected\r\n");
	} else if (status == SHADOW_ACK_ACCEPTED) {
		wmprintf("shadow publish state change accepted\r\n");
	}
}

void led_indicator_callback(const char *p_json_string,
			    uint32_t json_string_datalen,
			    jsonStruct_t *p_context) {
	int state;
	if (p_context != NULL) {
		state = *(int *)(p_context->pData);
		if (state) {
			led_on(led_1);
			led_1_state = 1;
		} else {
			led_off(led_1);
			led_1_state = 0;
		}
	}
}

static void aws_starter_demo(os_thread_arg_t data)
{
	char buf_out[BUFSIZE];
	char *property = NULL;
	ShadowParameters_t sp;

	int led_state = 0;
	jsonStruct_t led_indicator;

	int i, samples = SAMPLES;
	float result;
	ADC_CFG_Type config;
	uint16_t lpgValue_prev = 0 ;
	uint16_t lpgValue_curr = 0 ;
/* get default ADC gain value */
	adc_get_config(&config);
	wmprintf("Default ADC gain value = %d\r\n", config.adcGainSel);

	/* Modify ADC gain to 2 */
	adc_modify_default_config(adcGainSel, ADC_GAIN);

	adc_get_config(&config);
	wmprintf("Modified ADC gain value to %d\r\n", config.adcGainSel);

	adc_dev = adc_drv_open(ADC0_ID, ADC_CH0);

	led_indicator.cb = led_indicator_callback;
	led_indicator.pData = &led_state;
	led_indicator.pKey = "led";
	led_indicator.type = SHADOW_JSON_INT8;
	aws_iot_mqtt_init(&mqtt_client);

	int ret = aws_starter_load_configuration(&sp);
	if (ret != WM_SUCCESS) {
		wmprintf("aws shadow configuration failed : %d\r\n", ret);
		goto out;
	}

	ret = aws_iot_shadow_init(&mqtt_client);
	if (ret != WM_SUCCESS) {
		wmprintf("aws shadow init failed : %d\r\n", ret);
		goto out;
	}

	ret = aws_iot_shadow_connect(&mqtt_client, &sp);
	if (ret != WM_SUCCESS) {
		wmprintf("aws shadow connect failed : %d\r\n", ret);
		goto out;
	}

	/* indication that device is connected and cloud is started */
	led_on(board_led_2());
	wmprintf("Cloud Started\r\n");

	/* subscribe to delta topic of the configured thing */
	ret = aws_iot_shadow_register_delta(&mqtt_client, &led_indicator);
	if (ret != WM_SUCCESS) {
		wmprintf("return value is %d\r\n", ret);
	}

	while (1) {
		/* periodically check if any data is received on socket */
		aws_iot_shadow_yield(&mqtt_client, 1000);

		/* check if pushbutton a is pressed
		if (pushbutton_a_count_prev != pushbutton_a_count) {

			property = VAR_BUTTON_A_PROPERTY;
			make_str(property, pushbutton_a_count, buf_out,
				 sizeof(buf_out));
			wmprintf("Publishing '%s %s' to AWS\r\n", property,
				 buf_out);
*/
			/* publish incremented value on pushbutton press on
			 * configured thing
			ret = aws_iot_shadow_update(&mqtt_client,
						    sp.pMyThingName,
						    buf_out,
						    shadow_update_status_cb,
						    NULL,
						    10, true);
			if (ret != WM_SUCCESS) {
				wmprintf("Sending property failed\r\n");
			} else {
				pushbutton_a_count_prev = pushbutton_a_count;
			}
		}*/

		/* check if pushbutton b is pressed
		if (pushbutton_b_count_prev != pushbutton_b_count) {

			property = VAR_BUTTON_B_PROPERTY;
			make_str(property, pushbutton_b_count, buf_out,
				 sizeof(buf_out));
			wmprintf("Publishing '%s %s' to AWS\r\n",
				 property, buf_out);
 */
			/* publish incremented value on pushbutton press on
			 * configured thing
			ret = aws_iot_shadow_update(&mqtt_client,
						    sp.pMyThingName,
						    buf_out,
						    shadow_update_status_cb,
						    NULL, 10, true);

			if (ret != WM_SUCCESS) {
				wmprintf("Sending property failed\r\n");
			} else {
				pushbutton_b_count_prev = pushbutton_b_count;
			}
		}*/

#ifdef ADC_DMA
	adc_drv_get_samples(adc_dev, buffer, samples);
	for (i = 0; i < samples; i++) {
		result = ((float)buffer[i] / BIT_RESOLUTION_FACTOR) *
		VMAX_IN_mV * ((float)1/(float)(config.adcGainSel != 0 ?
		config.adcGainSel : 0.5));
		wmprintf("Iteration %d: count %d - %d.%d mV\r\n",
					i, buffer[i],
					wm_int_part_of(result),
					wm_frac_part_of(result, 2));
	}
#else
	for (i = 0; i < samples; i++) {

		buffer[0] = adc_drv_result(adc_dev);

		result = ((float)buffer[0] / BIT_RESOLUTION_FACTOR) *
		VMAX_IN_mV * ((float)1/(float)(config.adcGainSel != 0 ?
		config.adcGainSel : 0.5));

/*		 wmprintf("Iteration %d: count %d - %d.%d mV\r\n",
					i, buffer[0],
					wm_int_part_of(result),
					wm_frac_part_of(result, 2));*/
		os_thread_sleep(os_msec_to_ticks(50));

	}
#endif
	lpgValue_curr = wm_int_part_of(result);
	if ( lpgValue_prev - lpgValue_curr >= 10 || lpgValue_curr-lpgValue_prev >= 10){
		wmprintf("ADC Application Over %d\r\n",lpgValue_prev);


			property = VAR_LPG_VALUE;
			make_str(property, lpgValue_curr, buf_out,
				 sizeof(buf_out));
			wmprintf("Publishing '%s %d' to AWS\r\n",
				 property, lpgValue_curr);

			ret = aws_iot_shadow_update(&mqtt_client,
						    sp.pMyThingName,
						    buf_out,
						    shadow_update_status_cb,
						    NULL, 10, true);

			if (ret != WM_SUCCESS) {
				wmprintf("Sending property failed\r\n");
			} else {
				pushbutton_b_count_prev = pushbutton_b_count;
			}


	}

	lpgValue_prev = lpgValue_curr;

		/* On receiving led state change notification, change the state
		 * of the led in callback function and publish updated state on
		 * configured topic.
		 */
		if (led_1_state_prev != led_1_state) {
			property = VAR_LED_1_PROPERTY;
			make_str(property, led_1_state, buf_out,
				 sizeof(buf_out));
			wmprintf("Publishing '%s %s' to AWS\r\n", property,
				 buf_out);

			ret = aws_iot_shadow_update(&mqtt_client,
						    sp.pMyThingName,
						    buf_out,
						    shadow_update_status_cb,
						    NULL, 10, true);
			if (ret == WM_SUCCESS) {
				led_1_state_prev = led_1_state;
			}
		}
	}

	ret = aws_iot_shadow_disconnect(&mqtt_client);
	if (NONE_ERROR != ret) {
		wmprintf("aws iot shadow error %d\r\n", ret);
	}

out:
	os_thread_self_complete(NULL);
	return;
}

/* Event: AF_EVT_NORMAL_CONNECTED
 *
 * Station interface connected to home AP.
 *
 * Network dependent services can be started here. Note that these
 * services need to be stopped on disconnection and
 * reset-to-provisioning event.
 */
void wlan_event_normal_connected(void *data)
{
	int ret;
	/* Default time set to 1 October 2015 */
	time_t time = 1443657600;

	wmprintf("Connected successfully to the home network\r\n");

	if (!is_demo_started) {
		wmtime_time_set_posix(time);

		ret = os_thread_create(
			/* thread handle */
			&aws_starter_thread,
			/* thread name */
			"awsStarterDemo",
			/* entry function */
			aws_starter_demo,
			/* argument */
			0,
			/* stack */
			&aws_starter_stack,
			/* priority */
			OS_PRIO_3);
		if (ret != WM_SUCCESS) {
			wmprintf("Failed to start cloud_thread: %d\r\n", ret);
			return;
		}
		is_demo_started = true;
	}
}

void wlan_event_normal_link_lost(void *data)
{
	/* led indication to indicate link loss */
}

void wlan_event_normal_connect_failed(void *data)
{
	/* led indication to indicate link loss */
}

int main()
{




	if (wmstdio_init(UART0_ID, 0) != WM_SUCCESS) {
		return -WM_FAIL;
	}

	/*if (gpio_drv_init() != WM_SUCCESS) {
		wmprintf("gpio_drv_init failed\r\n");
		return -WM_FAIL;
		}*/
	/*adc initialization */
	if (adc_drv_init(ADC0_ID != WM_SUCCESS)){
			wmprintf("Cannot init ADC \n\r");
			return -1;
		}


	wmprintf("Build Time: " __DATE__ " " __TIME__ "\r\n");
	wmprintf("\r\n#### AWS ADC STARTER DEMO ####\r\n\r\n");

	configure_reset_to_factory();
	configure_led_and_button();

	/* This api adds aws iot configuration support in
	 * provisioning web application.
	 */
	enable_aws_config_support();
	wm_wlan_provision(UAP_SSID, UAP_PASSPHRASE);


		return 0;
}

Credits

Siddesh Shinde

Siddesh Shinde

1 project • 2 followers

Comments