From b7fa8c592f12d390ad3aa1b319e1f6c83b05b3c7 Mon Sep 17 00:00:00 2001 From: zelll Date: Tue, 25 Apr 2017 03:36:01 +0800 Subject: [PATCH] ADC extension for ESP32 (#1927) * added adc extension * add adc_number, for adc2 --- components/modules/Kconfig | 7 +++ components/modules/adc.c | 77 +++++++++++++++++++++++++ components/platform/include/platform.h | 14 +++++ components/platform/platform.c | 36 ++++++++++++ docs/en/modules/adc.md | 78 ++++++++++++++++++++++++++ mkdocs.yml | 1 + 6 files changed, 213 insertions(+) create mode 100644 components/modules/adc.c create mode 100644 docs/en/modules/adc.md diff --git a/components/modules/Kconfig b/components/modules/Kconfig index c0d67eb4..d28b0601 100644 --- a/components/modules/Kconfig +++ b/components/modules/Kconfig @@ -47,6 +47,13 @@ depends on LUA_BUILTIN_DEBUG endmenu +config LUA_MODULE_ADC + bool "ADC module" + default "n" + help + Includes the adc module. This module provides access to the + adc1 hardware. + config LUA_MODULE_BIT bool "Bit module" default "n" diff --git a/components/modules/adc.c b/components/modules/adc.c new file mode 100644 index 00000000..94cabee7 --- /dev/null +++ b/components/modules/adc.c @@ -0,0 +1,77 @@ +// Module for interfacing with adc hardware + +#include "module.h" +#include "lauxlib.h" +#include "platform.h" + + +// Lua: config( adc_id, bits ) +static int adc_set_width( lua_State *L ) +{ + int adc_id = luaL_checkinteger( L, 1 ); + MOD_CHECK_ID( adc, adc_id ); + int bits = luaL_checkinteger( L, 2 ); + + if (!platform_adc_set_width( adc_id, bits )) + luaL_error( L, "adc_set_width failed" ); + + return 0; +} + +// Lua: setup( adc_id, channel, atten ) +static int adc_setup( lua_State *L ) +{ + int adc_id = luaL_checkinteger( L, 1 ); + MOD_CHECK_ID( adc, adc_id ); + int channel = luaL_checkinteger( L, 2 ); + if (!platform_adc_channel_exists( adc_id, channel )) + luaL_error( L, "channel %d does not exist in ADC%d", ( unsigned )channel, ( unsigned )adc_id ); + + int atten = luaL_checkinteger( L, 3 ); + + if (!platform_adc_setup( adc_id, channel, atten )) + luaL_error( L, "adc_setup failed" ); + + return 0; +} + +// Lua: read( adc_id, channel ) +static int adc_read( lua_State *L ) +{ + int adc_id = luaL_checkinteger( L, 1 ); + MOD_CHECK_ID( adc, adc_id ); + int channel = luaL_checkinteger( L, 2 ); + if (!platform_adc_channel_exists( adc_id, channel )) + luaL_error( L, "channel %d does not exist in ADC%d", ( unsigned )channel, ( unsigned )adc_id ); + + int sample = platform_adc_read( adc_id, channel ); + if (sample == -1) + luaL_error( L, "adc_read failed" ); + lua_pushinteger( L, ( lua_Integer ) sample ); + return 1; +} + +// Lua: read_hall_sensor( ) +static int read_hall_sensor( lua_State *L ) +{ + int sample = platform_adc_read_hall_sensor( ); + lua_pushinteger( L, ( lua_Integer ) sample ); + return 1; +} + +// Module function map +static const LUA_REG_TYPE adc_map[] = +{ + { LSTRKEY( "setwidth" ), LFUNCVAL( adc_set_width ) }, + { LSTRKEY( "setup" ), LFUNCVAL( adc_setup ) }, + { LSTRKEY( "read" ), LFUNCVAL( adc_read ) }, + { LSTRKEY( "read_hall_sensor" ), LFUNCVAL( read_hall_sensor ) }, + { LSTRKEY( "ATTEN_0db" ), LNUMVAL( PLATFORM_ADC_ATTEN_0db ) }, + { LSTRKEY( "ATTEN_2_5db" ), LNUMVAL( PLATFORM_ADC_ATTEN_2_5db ) }, + { LSTRKEY( "ATTEN_6db" ), LNUMVAL( PLATFORM_ADC_ATTEN_6db ) }, + { LSTRKEY( "ATTEN_11db" ), LNUMVAL( PLATFORM_ADC_ATTEN_11db ) }, + { LSTRKEY( "ADC1" ), LNUMVAL( 1 ) }, + { LNILKEY, LNILVAL } +}; + +NODEMCU_MODULE(ADC, "adc", adc_map, NULL); diff --git a/components/platform/include/platform.h b/components/platform/include/platform.h index be08f8f7..309d88d3 100644 --- a/components/platform/include/platform.h +++ b/components/platform/include/platform.h @@ -87,6 +87,20 @@ uint8_t platform_sigma_delta_close( uint8_t channel ); uint8_t platform_sigma_delta_set_prescale( uint8_t channel, uint8_t prescale ); uint8_t platform_sigma_delta_set_duty( uint8_t channel, int8_t duty ); +// ***************************************************************************** +// ADC +int platform_adc_exists( uint8_t adc ); +int platform_adc_channel_exists( uint8_t adc, uint8_t channel ); +uint8_t platform_adc_set_width( uint8_t adc, int bits ); +uint8_t platform_adc_setup( uint8_t adc, uint8_t channel, uint8_t attn ); +int platform_adc_read( uint8_t adc, uint8_t channel ); +int platform_adc_read_hall_sensor( ); +enum { + PLATFORM_ADC_ATTEN_0db = 0, + PLATFORM_ADC_ATTEN_2_5db = 1, + PLATFORM_ADC_ATTEN_6db = 2, + PLATFORM_ADC_ATTEN_11db = 3, +}; // ***************************************************************************** // I2C platform interface diff --git a/components/platform/platform.c b/components/platform/platform.c index c5fb989f..1e870664 100644 --- a/components/platform/platform.c +++ b/components/platform/platform.c @@ -1,6 +1,7 @@ #include "platform.h" #include "driver/console.h" #include "driver/sigmadelta.h" +#include "driver/adc.h" #include int platform_init (void) @@ -152,7 +153,42 @@ uint8_t IRAM_ATTR platform_sigma_delta_set_duty( uint8_t channel, int8_t duty ) { return ESP_OK == sigmadelta_set_duty( channel, duty ) ? 1 : 0; } +// ***************************************************************************** +// ADC +int platform_adc_exists( uint8_t adc ) { return adc < 2 && adc > 0; } + +int platform_adc_channel_exists( uint8_t adc, uint8_t channel ) { + return (adc == 1 && (channel >= 0 && channel < 8)); +} + +uint8_t platform_adc_set_width( uint8_t adc, int bits ) { + bits = bits - 9; + if (bits < ADC_WIDTH_9Bit || bits > ADC_WIDTH_12Bit) + return 0; + if (ESP_OK != adc1_config_width( bits )) + return 0; + + return 1; +} + +uint8_t platform_adc_setup( uint8_t adc, uint8_t channel, uint8_t atten ) { + if (adc == 1 && ESP_OK != adc1_config_channel_atten( channel, atten )) + return 0; + + return 1; +} + +int platform_adc_read( uint8_t adc, uint8_t channel ) { + int value = -1; + if (adc == 1) value = adc1_get_voltage( channel ); + return value; +} + +int platform_adc_read_hall_sensor( ) { + int value = hall_sensor_read( ); + return value; +} // ***************************************************************************** // I2C platform interface diff --git a/docs/en/modules/adc.md b/docs/en/modules/adc.md new file mode 100644 index 00000000..b1a85458 --- /dev/null +++ b/docs/en/modules/adc.md @@ -0,0 +1,78 @@ +# ADC Module +| Since | Origin / Contributor | Maintainer | Source | +| :----- | :-------------------- | :---------- | :------ | +| 2017-04-22 | | | [adc.c](../../../components/modules/bthci.c)| + +The ADC module provides access to the in-built ADC1. + +On the ESP32 there are two ADC. ADC1 has 8 channels, while ADC2 has 10 channels. Currently, only ADC1 is supported. + +## adc.setwidth() + +The configuration is in effect for all channels of ADC1 + +#### Syntax +`adc.setwidth(adc_number, bits)` + +#### Parameters +- `adc_number` Only `adc.ADC1` now +- `bits` One of `9`/`10`/`11`/`12`. + +#### Returns +nil + + +## adc.setup() + +Configuration ADC1 capture attenuation of channels + +#### Syntax +`adc.setup(adc_number, channel, atten)` + +#### Parameters +- `adc_number` Only `adc.ADC1` now +- `channel` When using `adc.ADC1`: `0` to `7`. 0: GPIO36, 1: GPIO37, 2: GPIO38, 3: GPIO39, 4: GPIO32, 5: GPIO33, 6: GPIO34, 7: GPIO35 +- `atten` One of following constants + - `adc.ATTEN_0db` The input voltage of ADC will be reduced to about 1/1 (1.1V when VDD_A=3.3V) + - `adc.ATTEN_2_5db` The input voltage of ADC will be reduced to about 1/1.34 (1.5V when VDD_A=3.3V) + - `adc.ATTEN_6db` The input voltage of ADC will be reduced to about 1/2 (2.2V when VDD_A=3.3V) + - `adc.ATTEN_11db` The input voltage of ADC will be reduced to about 1/3.6 (3.9V when VDD_A=3.3V, maximum voltage is limited by VDD_A) + +#### Returns +nil + + +## adc.read() + +Samples the ADC. You should to call `setwidth()` before `read()`. + +#### Syntax +`adc.read(adc_number, channel)` + +#### Parameters +- `adc_number` Only `adc.ADC1` now +- `channel` 0 to 7 for adc.ADC1 + +#### Returns +the sampled value (number) + +#### Example +```lua +val = adc.read(adc.ADC1, 0) +``` + +## adc.read_hall_sensor() + +Read Hall sensor (GPIO36, GPIO39). We recommend using 12-bits width on ADC1. + +#### Syntax +`adc.read_hall_sensor()` + +#### Returns +the sampled value (number) + +#### Example +```lua +val = adc.read_hall_sensor() +``` + diff --git a/mkdocs.yml b/mkdocs.yml index e7e06b66..19c6132e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -31,6 +31,7 @@ pages: - Extension Developer FAQ: 'en/extn-developer-faq.md' - Support: 'en/support.md' - Modules: + - 'adc': 'en/modules/adc.md' - 'bit': 'en/modules/bit.md' - 'bthci': 'en/modules/bthci.md' - 'dht': 'en/modules/dht.md'