Thursday, August 11, 2016

ESP8266 - Internal ADC 2 - the easy way example



This is just a very quick example on how to add a Voltage Divider to the ESP8266 Internal ADC input to increase the ADC input range.

For more theory behind, please take a look at the previous related article: ESP8266 - Internal ADC


Today project:

      Measure a voltage input range from 0-5V with the ESP8266 internal ADC


What do we need:

  • 2 Resistors for the voltage divider, R1=105.6k, R2=24.08k. I am using here precision resistors and the values are measured values with a proper calibrated bench meter.
  • a good, trustable, calibrated ok Multimeter.
  • some wires to connect all together.


I will not insist on connections, take a deeper look at the previous article about


Voltage divider schematic and Vout (ADC input voltage) formula




How do we do it :


1. Measure your Max desired input voltage
    In my case, Max Input Voltage (Vmax) = 5.1919 (measured)



 
2. Measure Resistors values:
    R1 = 105.6k
    R2 = 24.08k


 
3. Check if Full Scale Value at the voltage divider output is inside the ADC defined domain:
  • Calculated : Vout = (R2/(R1+R2))*Vin = 0.964072733 V
  • Measured = 0.96038V
     Good enough for the precision we are looking for. ESP8266 ADC is 10bit only and not exactly the most accurate in town



4. Calculate Voltage Divider Ratio:
  • Vdivider Ratio= Max Input Voltage/Fullscale value =  5.405976676



5.  Read ADC value : 
       adcr = adc.read(0)
      print("    ReadADC     : "..adcr)
     Average result for adcr = 1017

THIS IS IMPORTANT !! It tell us that we are inside the ADC domain as adcr < 1024 !

IF adcr > 1023 then you need to adjust your voltage divider resistors to fit inside ADC domain!



6. Calculate LSB  in 2 ways to cross check that we have the right value:
  • LSB = Input Voltage read by multimeter/ADC readed Value = 
                   =  5.1919 / 1017 =  0.005105113 V
      OR
  • LSB = (ADC Input  pin read Voltage by multimeter/ADC readed Value/)*Vdivider Ratio = 
                  = (0.96038/1017)*5.405976676 = 0.005105113 V
       It looks that we have the right LSB Value for our exercise!

     If you want to know also the ADC LSB, then
       LSB = ADC Input  pin read Voltage by multimeter/ADC readed Value  =   
                =  0.96038/1017 = 0.000944346 V

    Guess what's happening if you multiply ADC LSB with Vdivider ratio :)




7. Software Implementation for the ADC read function:

 function readADC()
      ad = 0
      LSB = 0.005105113 --calibrate based on your voltage divider AND Vref!
      adcr = adc.read(0)
      ad= adcr*LSB       
      print("    ReadADC     : "..adcr)
      print("    Read Voltage     : "..ad)
      return ad
end

and some results in the terminal window:

> SENT: readADC()
readADC()
    ReadADC     : 1017
    Read Voltage     : 5.191899921
>






Thursday, August 4, 2016

ESP Basic -3 - PCF8574 I2C I/O 8 x independent switches example



8 x Independent switches driver Example :






  
   After doing last time the Mutually exclusive 8x Switch driver example, now is time for a 8 x independent switches implementation .


What we will need: 


      This is how is looking the setup on a breadboard, for a better visibility:





Software implementation:

Something to remember: 

  • PCF8574 can SINK but NOT SOURCE much current - 100uA only (it cannot output high, if you want). Look at the above example how is connected the LED for SINKING current.
  • Each of the 8 GPIOs have a minimum guaranteed sinking current of 10 mA per bit at 5 V.
  • Each pin needs its own limiting resistor to prevent damage to the device!! keep under 25mA/pin.
  • Maximum device limit sink current in about 80mA. If you need more, look after PCA8574 (200mA max sink current!)

For more details please take a look at the PCF8574 Datasheet


ESP8266 Basic code: 
let address = 32 'PCF8574 I2C Address

i2c.begin(address)
ss = 0 xor 255 'XOR - Bit masking for the desired I/O pins
i2c.write(ss)
i2c.end()
button "1", [1]
button "2", [2]
button "3", [3]
button "4", [4]
button "5", [5]
button "6", [6]
button "7", [7]
button "8", [8]
button "OFF", [9]
wait

[9]
i2c.begin(address)
ss = 0 xor 255 'XOR - Bit masking for the desired I/O pins
i2c.write(ss)
i2c.end()
wait

[1]
i2c.begin(address)
ss = ss xor 1   'XOR - Bit masking for the desired I/O pins
i2c.write(ss)
i2c.end()
wait

[2]
i2c.begin(address)
ss = ss xor 2
i2c.write(ss)
i2c.end()
wait

[3]
i2c.begin(address)
ss = ss xor 4
i2c.write(ss)
i2c.end()
wait

[4]
i2c.begin(address)
ss = ss xor 8
i2c.write(ss)
i2c.end()
wait

[5]
i2c.begin(address)
ss = ss xor 16
i2c.write(ss)
i2c.end()
wait

[6]
i2c.begin(address)
ss = ss xor 32
i2c.write(ss)
i2c.end()
wait

[7]
i2c.begin(address)
ss = ss xor 64
i2c.write(ss)
i2c.end()
wait

[8]
i2c.begin(address)
ss = ss xor 128
i2c.write(ss)
i2c.end()
wait

This is how is looking the interface in the Web Browser after running the above program:



PS: credit for the XOR Bit masking goes this time to Forlotto from the esp8266.com forum who posted quicker than me this elegant solution :)

ESP Basic -1 - PCF8574 I2C I/O Expander Driver example



Mutually-exclusive switch driver Example :







     Now that we have the I2C scanner program  that can help us to detect our I2C devices is time to move to some driver examples

    I think everybody know already the famous PCF8574. I have also cover it extendely in the previous Articles about, here for I/O input and here for output I/O.

    Now is time to put it at work also in ESP8266 Basic and see how is working.

   The example for today is a implementation of a mutually-exclusive switch that can be handy for many, many things as for example for doing the selection of a source in a Audio mixer or a any other analog path. Or driving Power relays.

   Mutually exclusive switch means  that when the corresponding switch button is pressed ON must also automatically turn the other sources OFF.



What we will need: 


      This is how is looking the setup on a breadboard, for a better visibility:





Software implementation:

Something to remember: 

  • PCF8574 can SINK but NOT SOURCE much current - 100uA only (it cannot output high, if you want). Look at the above example how is connected the LED for SINKING current.
  • Each of the 8 GPIOs have a minimum guaranteed sinking current of 10 mA per bit at 5 V.
  • Each pin needs its own limiting resistor to prevent damage to the device!! keep under 25mA/pin.
  • Maximum device limit sink current in about 80mA. If you need more, look after PCA8574 (200mA max sink current!)

For more details please take a look at the PCF8574 Datasheet


ESP8266 Basic code: 
let address=32     'PCF8574 I2C Address

button "1", [1]     'Define push buttons for each I/O pin
button "2", [2]
button "3", [3]
button "4", [4]
button "5", [5]
button "6", [6]
button "7", [7]
button "8", [8]
button "OFF", [9]  'Button for turning OFF all
wait

[9]
i2c.begin(address)    'Start I2C communication with device at 'address'
i2c.write(255)           'write the corresponding I/O pin value to register
i2c.end()                   'end I2C communication
wait

[1]
i2c.begin(address)
i2c.write(254)
i2c.end()
wait

[2]
i2c.begin(address)
i2c.write(253)
i2c.end()
wait

[3]
i2c.begin(address)
i2c.write(251)
i2c.end()
wait

[4]
i2c.begin(address)
i2c.write(247)
i2c.end()
wait

[5]
i2c.begin(address)
i2c.write(239)
i2c.end()
wait

[6]
i2c.begin(address)
i2c.write(223)
i2c.end()
wait

[7]
i2c.begin(address)
i2c.write(191)
i2c.end()
wait

[8]
i2c.begin(address)
i2c.write(127)
i2c.end()
wait

This is how is looking the interface in the Web Browser after running the above program:



Monday, August 1, 2016

ESP Basic - I2C Bus scanner example

UPDATE !! UPDATE !!UPDATE !!UPDATE !!
From ESPBasic Version 3.0 Alpha 43 you have also the i2c.setup function available!!

i2c.setup():

Will change the default pins for the i2c interface.  
i2c.setup({SDA}, {SCL})

----------------------------------------------------------------------------------------------------

From today I will start a new Series related with ESP Basic (www.esp8266basic.com)


When working with a lot of I2C devices one of the first thing that you need is a simple I2C scanner that can help you to identify the IC's and do some very basic troubleshooting.








What we will need: 
  • ESP8266 nEXT EVO Board
  • ESP8266 nEXT EVO - Analog Extension Board - AN1 (I2C devices onboard to test our scanner )
  • For programming and uploading the driver and the software we will use ESP8266 Basic .  


    nEXT EVO + AN-1 extension board



    I2C Scanner Software:

    UPDATE !! UPDATE !!UPDATE !!UPDATE !!
    From ESPBasic Version 3.0 Alpha 43 you have also the i2c.setup function available!!

    i2c.setup():

    Will change the default pins for the i2c interface.  
    i2c.setup({SDA}, {SCL})



              i2c.setup(4,5)
    for address = 1 to 127
       i2c.begin(address)
       stat = i2c.end()

       if stat < 1 then
         ' print stat
          wprint "Found I2C device at address: 0x" & hex(address)
          wprint " - > " & address
          wprint " <br>"
     endif
    next
    wait
     And the scanning result in browser :



    As you can see, has properly detected the I2C devices that are on the AN-1 Extension board:

    - PCF8574      - 8Bit I/O EXT port      - found at address 0x20 -> 32
    -
    LM75           - Temperature sensor    - found at address 0x48 -> 72
    -
    MCP4728    - 4x12Bit DAC              - found at address 0x60 -> 96
    -
    MCP3421    - 18Bit ADC                  - found at address 0x68 -> 10

Please keep in mind that in ESP Basic you have hardcoded I2C pins yet, SDA -> GPIO0 and SCL -> GPIO2.

Don't forget to add if needed pullup resistors on both lines, 4K7 should be OK. In case of AN-1 they are NOT needed.