Monday, May 18, 2015

P2 - Battery Monitor System - Web Server and data upload

 ================== W A R N I N G ! ! =================
Li-Ion batteries are very dangerous if not handled properly.
Use them only with proper protection circuits and chargers.
     Using any of the informations available on
 is on your own risk !!
    For any new CBDBv2 Evo orders/requests please feel free to use as usual:
     tech at
     If you want for your own experiments to order CBD v2 EVO bare PCBs only, you can also do it directly at Dirty PCBs, our preferred PCB House:

As promised, today we will continue with our Live Battery Monitor System.

Subjects of the day:
  •  WebServer interface for direct access
  •  Live Data upload over the Internet for wordwide access on

What we will need:  

For schematics, theory of operation and technical related things please see previous article: Battery LIve Monitor System

BLMS Software
  For programming CBDBv2 Board and uploading the drivers and the software we will continue to use the LuaUploader as before.

1. Define used GPIO pins and variables:

ADC_SRC = 5                    -- GPIO14 - select Voltage Divider / Current Inputsda=2                                   -- GPIO4  - SDA
scl=1                                    -- GPIO5  - SCL
gpio.mode(ADC_SRC,gpio.OUTPUT, gpio.PULLUP)
gpio.write(ADC_SRC,1)      -- Voltage Measurement - Voltage Divider Source selected
gpio.write(ADC_SRC,0)      -- Current Measurement - Current Shunt Monitor output selected
voltdiv= 0.00412                -- Voltage reading calibration
dival = 0.00096                  -- ADC volt/div value - CALIBRATE !! 
resdiv = 4.31447                -- Voltage Divider Ratio - CALIBRATE!!
divalI = 0.9425                  -- Current volt/div ratio - CALIBRATE!!
cpct = 0                              -- Calculated Delivered Energy
adcI = 0                             -- ADC readings -  Curent

adcV = 0                            -- ADC readings - Voltage
pwr = 0                              -- Calculate Power
t=0                                     -- time  

2. READ ADC Process function  and calculations 

function readUI()

      print("\nVoltage     : " ..string.format("%g",adcV).." V")

      print("Current     : " ..string.format("%g",adcI).." mA")
   --instantaneous Power consumption calculation
   pwr = adcI*adcV
   print("Power       : " ..string.format("%g",pwr).." mW")

   -- total delivered Energy calculation
    if (adcV > 1) then
      t = t +1
       print("Energy      : " ..string.format("%g",cpct).." W")
  else  tmr.stop(0)
        dtime = t/360         -- calculate discharge time

        print("Discharge Time: %.2fh  ",dtime)

3. BMS WebServer

        conn:send("HTTP/1.1 200 OK\n\n")
        conn:send("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"5\">")
        conn:send("<html><title>Battery Live Monitor System - ESP8266</title><body>")
        conn:send("<h1>Battery Live Monitor System - ESP8266</h1><BR>")
        conn:send("Voltage :<B><font color=red size=4>" 

                          ..string.format("%g",adcV).." V</font></b><br>")
        conn:send("Current :<B><font color=blue size=4>"

                         ..string.format("%g",adcI).." mA</font></b><br>")
        conn:send("Power   :<B><font color=red size=4>"

                        ..string.format("%g",pwr).." mW</font></b><br>")
        conn:send("Energy  :<B><font color=green size=4>"

                       ..string.format("%g",cpct).." Wh</font></b><br>")
        conn:send("<BR><BR><BR>Node.HEAP     : <b>" .. node.heap() .. "</b><BR>")
        conn:send("IP ADDR    :<b>".. wifi.sta.getip() .. "</b><BR>")
        conn:send("TMR.NOW    :<b>" .. .. "</b><BR<BR><BR>")
        conn:on("sent",function(conn) conn:close() end)
        conn = nil    

4. data upload  

 function sendDataTh()
    print("Sending data to")
    conn=net.createConnection(net.TCP, 0)
        conn:on("receive", function(conn, payload) print(payload) end)
        conn:send("GET /update?key=YOURKEYHERE&field1="..adcV.."&field2="..adcI.."&

        conn:send("Accept: */*\r\n")
        conn:send("User-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n")
        conn:on("sent",function(conn) print("Closing connection")
    conn:on("disconnection", function(conn) print("Got disconnection...")

5. MAIN program

If you have a new ESP module or is the first time when using it on a new WIFI network, don't forget to do the WIFI setup:

        -- One time ESP Setup --
         wifi.sta.config ( "YOUR_WIFI_SSID" , "PASSWORD" ) 

-- Read ADC data every 10s, print values on local Web interface and send them to
 tmr.alarm(0, 10000, 1, function() readUI() sendDataTh() end)

   For testing, just save the code on ESP as 'blmsweb.lua', restart ESP and run:   
            dofile("blmsweb.lua")      -- Start the Battery Live Monitoring System

            print(wifi.sta.getip())       --print your BMS WebServer IP address

BLMS - First RUN

  If you want the BLMS software to start automatically when your CBDBv2 Evo Board starts or reboots, then you neet to create and add some lines in your 'init.lua' file:
            dofile("blmsweb.lua")      -- Start the Battery Live Monitoring System

Save the code on ESP as 'init.lua', restart ESP. It should reboot and restart automatically the program.

Open your favorite Web browser and type your new BLMS Web Server IP address. If all ok, it should look like below :

BLMS - Web Server interface - 20ohm Load

Thingspeak data upload

I will not insist on the account setup, it's a pretty simple process:
  1. Sign Up for a ThingSpeak account
  2. Create a new Channel by going to your Channels page and clicking Create New Channel
  3. Update your Channel via URL:
  4. View your Channel feed:
Take a look at this Tutorial for more details for common devices and applications live data uploaded - 10ohm/10W Load for stress test calibration

You can also see on graph below the moment when battery protection kicks in, around 2.4V, 2.37745 V in this case, to be more exactly:

In the video below live monitoring data, with 10 and 20ohm resistor Load:


Nic Roche said...

When you say "like but who has voltage/current measurement capabilities" is the requirement for an ADC pin?

Unknown said...

It means literally to have voltage and current measurement capabilities in the desired range.
For example in case of CBDBv2 Evo Board you have in a default configuration a ADC input voltage range of 0-4.3V and current 0-2A. These can be easy changed as desired by changing the voltage divider ratio and current shunt resistor.
Take a look on the previous Battery Monitor System Article for more details about:

Melih said...
This comment has been removed by the author.
Melih said...

I cannot insert HyperText Markup Language code as a comment.

Melih said...

Thank you very much. It really helps. I have applied by changing it for my purpose.
But I think there are some mistakes.
In my setup, BMS server is not worked because of typo mistakes.
1. You should use ' instead of "
2. conn:send('') line is missing after first conn line

I did not tried Thingspeak part. But other parts are working, thank you.

Pulcinelli said...

Good afternoon,I have a problem in implementing LUA for the NodeMCU . In the code below , I realize the reading of a temperature sensor and other soil moisture and display the values ​​in an html page. If the value of soil moisture sensor is less than 25 % it should light up an LED . The question he performs this process only if I am accessing web page. If you close the page , it stops performing the reading. How do I get it to run code when you have no http client connected ?

Unknown said...

Hi Pulcinelli,

Just use a timer for your periodic readings that is not related at all with your Web server.

As you can see above such a timer is :

-- Read ADC data every 10s, print values on local Web interface and send them to
tmr.alarm(0, 10000, 1, function() readUI() sendDataTh() end)

You can change the call time for your own "readUI" function to your desired period.

Post a Comment