{"id":1922,"date":"2017-11-22T11:21:18","date_gmt":"2017-11-22T19:21:18","guid":{"rendered":"http:\/\/internetofhomethings.com\/homethings\/?p=1922"},"modified":"2017-11-22T11:21:18","modified_gmt":"2017-11-22T19:21:18","slug":"expanding-esp8266-adc-1-vdc-range","status":"publish","type":"post","link":"https:\/\/internetofhomethings.com\/homethings\/?p=1922","title":{"rendered":"Expanding ESP8266 ADC 1 VDC range"},"content":{"rendered":"<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1926\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc.jpg\" alt=\"\" width=\"230\" height=\"219\" \/><\/a><\/p>\n<p>An obvious weakness of the ESP8266 is the limited capability of it&#8217;s single ADC input. At best, the voltage range is 0-1 Vdc. While <a href=\"https:\/\/wp.me\/p5NRQ8-kB\" target=\"_blank\" rel=\"noopener\">coupling an Arduino module<\/a> to the ESP8266 solves this problem, is does introduce significant data acquisition delays for the Arduino-to-ESP8266 communication. A preferred solution uses the ESP8266 without requiring an additional processor.<\/p>\n<p>The method presented here adds 4 ADC inputs, each supporting voltages from 0-5V. In addition, one true DAC output is available to replace the PWM feature used for that purpose.<\/p>\n<p>And no additional processor is required.<\/p>\n<p>This is a very inexpensive addition, requiring hardware that acquired for approximately 1 USD.<\/p>\n<h2 style=\"text-align: center;\"><strong>ESP8266 ADC Range Improvement<\/strong><\/h2>\n<p>The enhancement is achieved by adding an external i2C bus ADC device to the ESP8266 system. This module,\u00a0PCF8591, was added to my project recently, purchased from <a href=\"https:\/\/www.aliexpress.com\/snapshot\/0.html?spm=a2g0s.9042647.0.0.b3rFpe&amp;orderId=87255213014466&amp;productId=32758644758\" target=\"_blank\" rel=\"noopener\">Ali-Express<\/a> for 93 cents. It sports 4 ADC channels, one DAC channel, a potentiometer, thermister, and a photo-sensor. But for my needs, I have disabled the additional components and use it strictly as a 4-channel ADC.<\/p>\n<p>The device uses an i2C bus, which requires 2 digital pins (any two) to operate.<\/p>\n<p>There are two limitations I discovered while testing this module, neither of which adversely impact it&#8217;s functionality in my application.<\/p>\n<ol>\n<li>The ADCs and DAC are 8-bit devices. This results in a somewhat course resolution of 19mV-per-bit when using a 5V reference.<\/li>\n<li>The DAC range is linear 0-4Vdc, but compresses beyond that and tops out at 4.25Vdc.<\/li>\n<\/ol>\n<p>Even with these constraints, I was still pleased to have the capability of measuring voltages 0-5V. This was a huge improvement over the ESP8266 native 0-1Vdc ADC.<\/p>\n<p>The ADCs can be used single-ended (4 channels) or differential (2 channels), an added capability which allows you to measure signals with a common-mode voltage. Changing the ADC mode is a simple matter of changing the control byte when setting up the ADC for a measurement. As you will see in the sketch below, single-ended measurements are made using the control bytes:<\/p>\n<pre class=\"easycode; title:;lang:;\">#define PCF8591_ADC_CH0             0x40 \/\/Measure Ain0 single-ended at CH0\r\n#define PCF8591_ADC_CH1             0x41 \/\/Measure Ain1 single-ended at CH1\r\n#define PCF8591_ADC_CH2             0x42 \/\/Measure Ain2 single-ended at CH2\r\n#define PCF8591_ADC_CH3             0x43 \/\/Measure Ain3 single-ended at CH3<\/pre>\n<p>Other options, if desired, would expand the set of control bytes:<\/p>\n<pre class=\"easycode; title:;lang:;\">#define PCF8591_ADC_CH0             0x40   \/\/Measure Ain0 single-ended at CH0\r\n#define PCF8591_ADC_CH1             0x41   \/\/Measure Ain1 single-ended at CH1\r\n#define PCF8591_ADC_CH2             0x42   \/\/Measure Ain2 single-ended at CH2\r\n#define PCF8591_ADC_CH3             0x43   \/\/Measure Ain3 single-ended at CH3\r\n\r\n#define PCF8591_ADC_DIFF_CH0CH3_CH0 0x50   \/\/Measure Ain0-Ain3 differentially at CH0\r\n#define PCF8591_ADC_DIFF_CH1CH3_CH1 0x51   \/\/Measure Ain1-Ain3 differentially at CH1\r\n#define PCF8591_ADC_DIFF_CH2CH3_CH2 0x52   \/\/Measure Ain2-Ain3 differentially at CH2\r\n\r\n#define PCF8591_ADC_MIXED_CH0       0x60   \/\/Measure Ain0 single=ended at CH0\r\n#define PCF8591_ADC_MIXED_CH1       0x61   \/\/Measure Ain1 single=ended at CH1\r\n#define PCF8591_ADC_MIXED_CH2_CH3   0x62   \/\/Measure Ain2-Ain3 differentially at CH2\r\n\r\n#define PCF8591_ADC_DIFF_CH0CH1_CH0 0x70   \/\/Measure Ain0-Ain1 differentially at CH0\r\n#define PCF8591_ADC_DIFF_CH2CH3_CH1 0x71   \/\/Measure Ain2-Ain3 differentially at CH1<\/pre>\n<p>&nbsp;<\/p>\n<h2 style=\"text-align: center;\"><strong>ADC Module Interfaces<\/strong><\/h2>\n<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc_pic.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1928\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc_pic.jpg\" alt=\"\" width=\"765\" height=\"438\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc_pic.jpg 765w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc_pic-300x172.jpg 300w\" sizes=\"auto, (max-width: 765px) 100vw, 765px\" \/><\/a><\/p>\n<p>The ESP8266 interface requires 4 signals:<\/p>\n<ol>\n<li>Vcc (5 Vdc, before the 3.3 Vdc regulator)<\/li>\n<li>Gnd (Ground)<\/li>\n<li>SDA (Any ESP8266 Digital pin &#8211; GPIO4 in this example)<\/li>\n<li>SCL (Any EAP8266 Digital pin &#8211; GPIO2 in this example)<\/li>\n<\/ol>\n<p>The jumper pins (P4-P6) are removed for 4-channels ADC configuration.<\/p>\n<p>Here is the minimal Arduino sketch I used to test this ADC. As you can see, the ADC read code can easily be included in a more complex sketch.<\/p>\n<pre class=\"easycode; title:;lang:;\">#include \"Wire.h\"\r\n#define PCF8591 (0x90 &gt;&gt; 1)\r\n#define PCF8591_DAC_ENABLE 0x40\r\n#define PCF8591_ADC_CH0 0x40   \/\/Measure Ain0 single-ended at CH0\r\n#define PCF8591_ADC_CH1 0x41   \/\/Measure Ain1 single-ended at CH1\r\n#define PCF8591_ADC_CH2 0x42   \/\/Measure Ain2 single-ended at CH2\r\n#define PCF8591_ADC_CH3 0x43   \/\/Measure Ain3 single-ended at CH3\r\n\r\n#define SDA 4\r\n#define SCL 2\r\nbyte adcvalue0, adcvalue1, adcvalue2, adcvalue3;\r\nbyte dac_value=0;\r\nbyte adc_value;\r\n\r\nvoid putDAC(byte dac_value)\r\n{\r\n  Wire.beginTransmission(PCF8591);  \/\/Calls the 8591 to attention.\r\n  Wire.write(PCF8591_DAC_ENABLE);   \/\/Send a DAC enable word.\r\n  Wire.write(dac_value);            \/\/Send the desired DAC value (0-255)\r\n  Wire.endTransmission();\r\n}\r\n\r\nbyte getADC(byte config)\r\n{\r\n  Wire.beginTransmission(PCF8591);\r\n  Wire.write(config);\r\n  Wire.endTransmission();\r\n  Wire.requestFrom((int) PCF8591,2);\r\n  while (Wire.available()) \r\n  {\r\n    adc_value = Wire.read(); \/\/This needs two reads to get the value.\r\n    adc_value = Wire.read();\r\n  }\r\n  return adc_value;\r\n}\r\n \r\nvoid setup()\r\n{\r\n   Wire.begin(SDA,SCL);\r\n   Serial.begin(115200);\r\n   putDAC(0);\r\n   Serial.println(\"dac,ain0,ain1,ain2,ain3\");\r\n}\r\n \r\nvoid loop()\r\n{\r\n   adcvalue0 =  getADC(PCF8591_ADC_CH0);\r\n   adcvalue1 =  getADC(PCF8591_ADC_CH1);\r\n   adcvalue2 =  getADC(PCF8591_ADC_CH2);\r\n   adcvalue3 =  getADC(PCF8591_ADC_CH3);\r\n\r\n   Serial.print(dac_value++);\r\n   Serial.print(\",\");\r\n   Serial.print(adcvalue0);\r\n   Serial.print(\",\");\r\n   Serial.print(adcvalue1);\r\n   Serial.print(\",\");\r\n   Serial.print(adcvalue2);\r\n   Serial.print(\",\");\r\n   Serial.print(adcvalue3);\r\n   Serial.println();\r\n   \r\n   putDAC(dac_value);\r\n    \r\n   delay(100);\r\n}<\/pre>\n<p>This simple sketch configures the I2C library to attach to ESP8266 GPIO2 and GPIO4 and loop through a sequence of setting the DAC and reading all 4 ADC channels. For this setup, the DAC output is connected to all 4 ADC inputs and jumpers P4-P6 are removed. As one would expect, for each DAC setting, identical ADC values are measured for all 4 ADCs. But there are some deviations from the DAC setting:<\/p>\n<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc-data.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1933 size-full\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc-data.jpg\" alt=\"\" width=\"430\" height=\"5162\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc-data.jpg 430w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc-data-25x300.jpg 25w\" sizes=\"auto, (max-width: 430px) 100vw, 430px\" \/><\/a><\/p>\n<h2 style=\"text-align: center;\"><strong>DAC Limitations<\/strong><\/h2>\n<p>The ADC measured values deviate from the DAC setting by no more than 1 bit (~ 20mV) from 0-2 Vdc. This deviation increases to 4 bits around 4 Vdc, with the DAC output topping out at about 4.2 Vdc.<\/p>\n<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc-chart.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1934\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc-chart.jpg\" alt=\"\" width=\"483\" height=\"291\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc-chart.jpg 483w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/adc-chart-300x181.jpg 300w\" sizes=\"auto, (max-width: 483px) 100vw, 483px\" \/><\/a><\/p>\n<p>From this we can conclude that the DAC has a functional range from 0-4 Vdc with an error no greater than 4 bits (80mV). Not super accurate, but it is adequate for many applications.<\/p>\n<p>I measured the ADC output with a DVM (digital voltmeter) to confirm the DAC output never exceeded 4.2 Vdc.<\/p>\n<h2 style=\"text-align: center;\"><strong>ADC Voltage Range<\/strong><\/h2>\n<p>And to confirm the ADC has a full range of 0-5VDC (0-255 byte value), I applied 5 Vdc to one of the Ain inputs and verified the measure value as 255 (5 Vdc). I also used the built-in potentiometer to swing the ADC measurements between 0 and 255 (0-5 Vdc). With a slight modification to the sketch to display the ADC readings from the potentiometer (Ain3) in Vdc, we observe good correlation between the applied voltage and the ADC measurement.<\/p>\n<p style=\"text-align: center;\"><iframe loading=\"lazy\" src=\"https:\/\/www.youtube.com\/embed\/28-B3aJ1FCU\" width=\"560\" height=\"315\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\n<p>Great!<\/p>\n<p>This confirms the ADC can read voltages over the full 0-5 Vdc range.<\/p>\n<h2 style=\"text-align: center;\"><strong>Expanding the Channels<\/strong><\/h2>\n<p>The\u00a0PCF8591 ADC has 3 programmable address lines which makes it possible to expand the ADC channel count from 4 to 32. Even better, this still only requires 2 ESP8266 digital (GPIO) channels as the control pins would all be connected in parallel.<\/p>\n<p>But there is a catch with the XL-40 carrier module that holds the PCF8591. The 3 address lines are hard-wired to ground. So, to expand the channels, you would need to cut the traces (lift the pins) to set a different address for each added module in your ESP8266 configuration.<\/p>\n<p>No impossible, but you have to be careful not to overheat the device when desoldering the pins.<\/p>\n<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/expand.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1938\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/expand.jpg\" alt=\"\" width=\"765\" height=\"438\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/expand.jpg 765w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/expand-300x172.jpg 300w\" sizes=\"auto, (max-width: 765px) 100vw, 765px\" \/><\/a><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/pcf8591.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1935\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/pcf8591.jpg\" alt=\"\" width=\"394\" height=\"315\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/pcf8591.jpg 394w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2017\/11\/pcf8591-300x240.jpg 300w\" sizes=\"auto, (max-width: 394px) 100vw, 394px\" \/><\/a><\/p>\n<h2 style=\"text-align: center;\">In Closing<\/h2>\n<p>Here is a low-cost (1 USD) addition to your ESP8266 setup that expands the ADC capability to 4 channels with the bonus of a real DAC output. While the DAC is limited to a 0-4Vdc range, you have the full 0-5 Vdc available for analog measurements with reasonable accuracy.<\/p>\n<p>Hope you find this a useful addition to your projects.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>An obvious weakness of the ESP8266 is the limited capability of it&#8217;s single ADC input. At best, the voltage range is 0-1 Vdc. While coupling an Arduino module to the &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,10],"tags":[162,161],"class_list":["post-1922","post","type-post","status-publish","format-standard","hentry","category-alltheposts","category-esp8266","tag-betteresp8266adc","tag-esp8266-adc"],"_links":{"self":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1922","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1922"}],"version-history":[{"count":12,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1922\/revisions"}],"predecessor-version":[{"id":1940,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1922\/revisions\/1940"}],"wp:attachment":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1922"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1922"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1922"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}