OCROBOT ALPHA ESP8285 + LI POWER 电池电量监视器
之前那个开箱帖做了很多的程序测试,看上比较凌乱。
这次单独发一帖整理一个使用 ESP8285 + ADS1015 + 锂电模块 的应用实例程序:电池电量监视器
除了上面说那套OC开发板之外还需要一个台PC电脑,chrome浏览器65版,一个和PC联网的带WIFI功能路由器。
8285的主程序代码需要自行修改填上WIFI SSID和密码,8285的IP是自动获取的,要访问到监视器页面就需要知道IP地址,我是在路由查出来的。
监视器页面有一个gogogo的按钮,点击后就会开始记录电池电量变化,每隔10分钟刷新一次,同时绘制柱状图表
从满电开始到完全放电可能会超过10小时,如果电脑进入休眠,定时记录也会停止,所以最好把休眠禁止掉
这里是主程序代码
//8285链接wifi路由 IP是动态获取的 至于怎么获得这个IP自己想办法 访问 http://x.x.x.x/read_adc_chart.htm 可见网页
//页面使用SPIFFS文件保存,页面定时异步更新当前所有adc数值,并且显示电量图表
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <FS.h> //文件系统库SPIFFS
#include <Wire.h> //iic接口库
#include <Adafruit_ADS1015.h> //adc库,居然是出自Ada的
const char *ssid = "你的WIFI"; //wifi ssid
const char *password = "你的WIFI密码"; //wifi 密码
Adafruit_ADS1015 ads; //定义adc变量
ESP8266WebServer server ( 80 ); //定义web服务
void handleNotFound() {//404页面
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for ( uint8_t i = 0; i < server.args(); i++ ) {
message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
}
server.send ( 404, "text/plain", message );// 返回信息给浏览器(状态码,Content-type, 内容)
}
void ra_page() {//读取adc数值页面
if(SPIFFS.exists("/read_adc_chart.htm")){//如果文件存在
File file = SPIFFS.open("/read_adc_chart.htm", "r"); //打开文件
size_t sent = server.streamFile(file, "text/html");//发送内容
file.close(); //关闭文件
return;
}
else
{
handleNotFound(); //404
}
}
void adc_values() {//返回adc值
String p= "";
int adc;
unsigned long systime;
systime=millis(); //系统时间
p= String(systime);
adc = ads.readADC_SingleEnded(0); //获取各路adc的数值
p=p+","+String(adc);
adc = ads.readADC_SingleEnded(1);
p=p+","+String(adc);
adc = ads.readADC_SingleEnded(2);
p=p+","+String(adc);
adc = ads.readADC_SingleEnded(3);
p=p+","+String(adc);
server.send(200, "text/plain", p);//抛出返回信息如果整个过程都没出错,应该返回这样的信息 系统运行毫秒数,0路电压,1路电压,2路电压,3路电压所有数字之间均以逗号分隔
}
void setup() {
WiFi.begin ( ssid, password );//wifi链接
delay(3500);
SPIFFS.begin();//这个文件系统实例好像在头文件里已经定义好了,无需声明直接开始工作吧
//web服务请求响应对象
server.on ( "/inline", []() {server.send ( 200, "text/plain", "this works as well" );} ); //这句意义重大:当主页面文件无法顺利上存时,至少能通过inline显示一个“好”页面
server.on ( "/read_adc_chart.htm", ra_page );
server.on ( "/adc", adc_values );
server.onNotFound ( handleNotFound );
server.begin(); //启动web服务
ads.begin();//adc开始工作吧
}
void loop() {
server.handleClient();
}
由于这个程序是在Arduino 1.6.12 + Esp866 2.3.0版本下写的,上存程序和文件都需要手动把GPIO 0接地
如果想更加了解这个问题 请看这里 http://www.geek-workshop.com/thread-37411-1-1.html
接着是页面代码,页面文件的位置在主程序目录的data文件夹下
<html>
<head>
<title>read adc values show chart</title>
<!--ESP8285 + ads1015-->
<style>
canvas {
cursor: pointer;
border: 1px solid black;
}
</style>
<script type="text/javascript">
var ar_time = new Array();
var ar_volt = new Array();
function read_adc()//get adc values
{
var url;
url ="/adc";
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onreadystatechange = function(e){
if (xhr.readyState == 4) {
var rtn = xhr.responseText;
document.getElementById("textarea").value+= rtn+"\n";
var ar_str = rtn.split(",");
ar_time.push(ar_str);
ar_volt.push(ar_str);
}
};
xhr.send();
draw_chart();
}
function draw_chart() {
var canvas;
var context;
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.lineWidth = 25;
context.strokeStyle = "#cd2828";
var i,v;
for (i = 0; i < ar_volt.length; i++) {
context.moveTo(65+i*25, 400);
v=ar_volt;
context.lineTo(65+i*25, 1400-v);
context.save();
context.translate(65+i*25,410);
context.rotate(Math.PI / 2);
var n,h;
n=Math.floor(ar_time / (1000*60) );
h=Math.floor(n / 60);
n= n % 60;
context.fillText(h+" : "+n,0,0);
var m=ar_volt*0.003;
context.fillText(m.toFixed(3)+'v',0,13);
context.restore();
}
context.stroke();
}
function button_gogogo() //btn_go make anything start once
{
document.getElementById("btn_go").disabled = true;
read_adc();
self.setInterval('read_adc()',600000);
}
</script>
</head>
<body>
<textarea id="textarea" rows=5 cols=100></textarea>
<input id="btn_go" type="button" value="gogogo" onclick="button_gogogo()" />
<div>
<canvas id="canvas" width="1300" height="500"></canvas>
</div>
</body>
</html>
页面没写什么注释,因为整个文件会原原本本地上存到8285,就算注释也需要占用8285宝贵的存储空间,而且读取文件的速度也不怎么快。
其实注释也没什么用的,无论我怎么写也无法说清楚这个页面为什么只能在chrome下正常工作,而Internet Explorer则不行。
所以如果前端出了什么问题,一定就是浏览器的错
如果你想更加了解SPIFFS文件 请参阅这里 https://github.com/esp8266/arduino-esp8266fs-plugin
到目前为止我未能完完整整地玩一次从满电倒完全放电的测试,那么你想试试么?
由于我手上那块8285的丝印并没有很清晰地标出ADC信息,所以这里补充说明一下接线
ADC2要接上18650的正极,就是下图那个绿圈
https://raw.githubusercontent.com/FreezingEye/pedrail-1.5/master/forum_image/20180429/ADS1015.png
今日测试了8个小时,情况如下
wing 发表于 2018-5-2 21:40
今日测试了8个小时,情况如下
还是挺耗电的。。。 本帖最后由 wing 于 2018-5-5 13:38 编辑
终于完成了一次从满电到终止放电的过程了,历时超过15小时
图表改进了,蓝色顺眼些吧,而且看起来不那么梯级了
每50秒获取一次电压,然后绘制宽度为1像素的柱状图,其实就是一条线,这样看起来比较平滑
每12次取值绘制下面的文字,也就是每隔10分钟有一次文字记录
主程序还是一样,下面是改进后的页面代码
<html>
<head>
<title>battery chart</title>
<!--ESP8285 + ads1015-->
<style>
canvas {
cursor: pointer;
border: 1px solid black;
}
</style>
<script type="text/javascript">
var ar_time = new Array();
var ar_volt = new Array();
function read_adc()//get adc values
{
var url;
url ="/adc";
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onreadystatechange = function(e){
if (xhr.readyState == 4) {
var rtn = xhr.responseText;
document.getElementById("textarea").value+= rtn+"\n";
var ar_str = rtn.split(",");
ar_time.push(ar_str);
ar_volt.push(ar_str);
}
};
xhr.send();
draw_chart();
}
function draw_chart() {
var canvas;
var context;
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.lineWidth = 1;
context.strokeStyle = "#2828cd";
var i,v;
var vtime;
for (i = 0; i < ar_volt.length; i++) {
context.moveTo(35+i, 650);
v=ar_volt;
context.lineTo(35+i, 1400-v);
if (i % 12 ==0) {
context.save();
context.translate(35+i,660);
context.rotate(Math.PI / 2);
var s,n,h;
s=Math.floor(ar_time / 1000 );
n=Math.floor(s / 60 );
h=Math.floor(n / 60);
if (h<10){
vtime='0'+h;
}else{
vtime=h;
}
n= n % 60;
if (n<10){
vtime=vtime+' : 0'+n;
}else{
vtime=vtime+' : '+n;
}
s= s % 60;
if (s<10){
vtime=vtime+' : 0'+s;
}else{
vtime=vtime+' : '+s;
}
var m=ar_volt*0.003;
context.fillText(m.toFixed(3)+'V '+vtime,0,0);
context.restore();
}
}
context.stroke();
}
function button_gogogo() //btn_go make anything start once
{
document.getElementById("btn_go").disabled = true;
read_adc();
self.setInterval('read_adc()',50000);//50s once
}
</script>
</head>
<body>
<textarea id="textarea" rows=5 cols=100></textarea>
<input id="btn_go" type="button" value="gogogo" onclick="button_gogogo()" />
<div>
<canvas id="canvas" width="1800" height="750"></canvas>
</div>
</body>
</html>
整体来看分三段
从满电到3.7V,以一个基本相等的速度放电,这种状态维持6个多小时
3.7~3.4,以另一个基本相等的速度放电,这种状态维持8个小时
3.4之后就开始跳水了,一个小时不到就放尽了
来分析一下,最后10分钟的获取的电压数据
55806894,1010
55856890,1004
55906899,997
55956898,990
56006887,983
56056895,974
56106892,964
56156893,953
56206899,938
56256895,919
56306895,895
56356900,862
基本上就是到了3V就开始断崖式下跌,最后获取到的电压是 2.586V。
毅神说过保护电压大概在2.5左右,从实验数据来看基本吻合 :o有意思。。。按照理论推算,此电池标称容量为2AH,实际测试容量约为1.8~1.9Ah左右(5A负载), 理论容量为3.7X2=7.4Wh 。 ESP8285的待机功耗约为23ma,加上外设 ADC usb等 估计会有40-50ma的负载, 也就是说5x0.045=0.225W(取5V不取3.3V 因为板载使用的是线性稳压器,多余的能量是耗散掉的)
考虑升压器综合效率85%计算7.4x0.85 = 6.29
6.29÷0.225 = 约为27小时与实际测试值接近
误差主要来源就是wifi通讯时的发射功耗 会增加到200-300ma
:lol根据实验数据,以后可以在理论值除以2的基础上推算wifi通讯情况下的实际耗电了
测试一下,大家能不能看到下面的图
https://raw.githubusercontent.com/FreezingEye/pedrail-1.5/master/forum_image/20180928/图表版本电池用量.webp
页:
[1]