Noduino OpenPlant

来自Jack's Lab
跳转到: 导航, 搜索

目录

1 Overview

OpenPlant-01.jpgOpenPlant-02.jpg


2019-05-13:

OpenPlant-20190513.jpgOpenPlant-20190512.jpg




2 太阳能补电

Openplant-lowpower-01.jpg


2.1 太阳能电池的 I-V特性

太阳能电池一般由 PN 结组成,PN 结中的光能 (光子) 通过导致电子和空穴的重新组合而产生电流。由于 PN 结的特性类似于二极管的特性,我们一般以下图中所示的电路作为太阳能电池特性的一个简化模型:

Solar-panel-model.jpg

电流源 Iph 产生的电流和太阳能电池上的光量度成正比。在没有负载连接的时候,几乎所有产生的电流都流过二极管 D,其正向电压决定着太阳能电池的开路电压 (Voc)。该电压会因各种类型太阳能电池的特性不同而有所差异。但是,对于大多数硅电池而言,这一电压都在 0.5V 到 0.6V 之间,这也是 PN 结二极管的正常正向电压。


在实际太阳能电池应用中,并联电阻 Rp 的泄漏电流很小,而 Rs 则会产生连接损耗。下图展示了太阳能电池在输出上的特性。由于串联电阻 Rs 的原因,电压会稍有下降。然而,有时如果通过内部二极管的电流太小,会导致偏置不够,并且穿过它的电压会随着负载电流的增加而急剧下降。最后,如果所有电流都只流过负载而不流过二极管,输出电压就会变为零。这个电流被称为太阳能电池的短路电流 Isc。Isc 和 Voc 都是定义太阳能工作性能的主要参数之一。

Solar-panel-i-v.jpg

太阳能电池可认为是“电流限制”型电源,输出电压会随着输出电流的增加而降低,并在负载电流达到短路电流时降为零。 其极端情况为:

  • 当输出电压为其最大数值 (Voc) 时,输出电流为零
  • 当输出电流达到最大值 (Isc),但输出电压为零


曲线关系为:

Solar-panel-output.jpg

则输出功率也是动态变化的,其极值为最大功率点 (MPP)。

实验记录出输出曲线,就能求得最大矩形面积的点 MPP,一般都会在输出特性曲线的下半部分的某个位置,其确切位置会因入射光线和环境温度的不同而不同


太阳能电池的输出电流随光照强度的变化而变化,上下电流波动较大,一般不能直接给用电系统供电,需将能量先存储于电池中,然后通过电池为系统供电。


2.2 电池板

  • 多晶太阳能电池板 4V/30mA,65mm x 28mm x 3mm
  • 多晶太阳能电池板 5.5V/60mA,60mm x 60mm x 3mm


2.3 CN3083

芯片内部集成有 8 模数转换器,能够根据输入电压源的电流输出能力自动调节充电电流,用户不需要考虑最坏情况。当输入电压过低时,锁存,自动再充电;当输入电压掉电时,CN3083自动进入低功耗的睡眠模式,此时电池的电流消耗小于 3 uA

充电电流通过一个外部电阻设置。

内部固定的恒压充电电压为 4.2V,也可以通过一个外部电阻往高处调节。

热调制电路可以在器件的功耗比较大或者环境温度比较高的时候将芯片温度控制在安全范围内。

其它功能包括电池温度监控以及充电状态/充电结束状态指示等


2.3.1 预充电状态

在充电周期的开始,如果电池电压 Kelvin 检测输入端 (FB) 的电压低于3V,充电器处于预充电状态,充电器以恒流充电模式充电电流的 10% 对电池进行充电。


2.3.2 输入电压源限流模式

当 CN3083 输入电压源的电流输出能力(带负载能力)小于第 2 管脚的电阻 RISET 所设置的充电电流时,器件内部的 8 位 ADC 根据输入电压源的电流输出能力自动控制充电电流,此时实际充电电流可能小于所设置的充电电流,但是在保证 CN3083 第 4 管脚 VIN 的电压不低于最小工作电压的前提下,能够使得充电电流最大化


即当输出电流小于设置电流时,判断为光照不足,自动调节输出电流,优先保证电池板的输出电压。在这种模式下用户只要根据输入电压源的最大电流输出能力设置充电电流即可


2.3.3 电池电压Kelvin检测

CN3083 有一个电池电压 Kelvin检测输入端 (FB),此管脚通过芯片内部的精密电阻分压网络连接到恒压充电的误差放大器。

FB 管脚可以直接连接到电池的正极,这样可有效避免电池正极和 CN3083 的第 5 管脚 BAT 之间的寄生电阻(包括导线电阻,接触电阻等)对充电的影响。这些寄生电阻的存在会使充电器过早的进入恒压充电状态,延长充电时间,甚至使电池充不满,通过使用电池电压 Kelvin 检测可以解决这些问题。

如果将 CN3083 的电池电压 Kelvin 检测输入端 (FB) 悬空,那么CN3083一直处于预充电状态,充电电流为所设置的恒流充电电流的 1/10


2.3.4 充电结束

在恒压充电状态,当施加在 CN3083 的第 4 管脚 VIN 的电压大于 4.45V,并且当充电电流小于所设置的恒流充电电流的 1/10 时,充电周期结束。

在输入电压源限流模式,即使充电电流小于所设置的恒流充电电流的 1/10,充电也将继续,不会结束。这样可以保证即使在输入电压源的电流输出能力很微弱的情况下,也能为电池充电。


2.3.5 参考电路

CN3083-Sch.jpg


2.3.6 Datasheet

CN3083 Datasheet


2.3.7 其他选择

太阳能充电管理芯片其他选择



2.4 CN3082

CN3083 + 恒流后的维持电流模式 + 外部电阻设置维持电流

当 FB 管脚的电压上升到 2.445V 时,充电器结束恒流充电状态,进入维持充电状态,此时电池端对应的的恒流充电终止电压为:

 VBAT=2.445×(1+R3/R4) 

此模式用于支持更多类型电池充电,比如:镍氢电池,磷酸铁锂电池和铅酸电池


CN3082 Datasheet



3 电池电压监控

  VBAT ------ 1M 1% ------ 200K 1% ------ GND
                          |
                          |
                         ADC


int ad = system_adc_read();
float V = (ad / 1024.0) * (1000.0 + 200)/200;

电流消耗:3.7 / (220+100) = 0.0112 mA = 11.2 uA

如果换成: 200K + 1M,则电流消耗会降到 3 uA 左右


Openplant-battery-monitor.jpg


char *get_vbat(float *fv)
{
    int uv = mcp342x_get_uv();

    float vbat = uv * (99.985 + 219.35) / 99.985 / 1000000.0;

    dtostrf(vbat, 6, 2, g_vbat);

    if(fv != NULL)
        *fv = vbat;

    unsigned char *p = g_vbat;
    while(isspace(*p)) p++;

    return p;
}

Openplant-bat-curve.jpg



4 低功耗优化

4.1 Base

  • Transfer to use raw sdk done
  • Disable Ping done
  • Change the mode of mcp342x to One-Shot Conversion with 1 SPS done



4.2 phy_get_vdd33()

Remove the mcp342x, use the internal phy_get_vdd33()


system_get_vdd33 功能: 


测量 VDD3P3 管脚 3 和 4 的电压值,单位:1/1024 V

  • system_get_vdd33 必须在 TOUT 管脚悬空的情况下使⽤,否则值不准
  • TOUT 管脚悬空的情况下,esp_init_data_default.bin(0~127byte)中的第 107 byte 为 "vdd33_const",必须设为 0xFF,即 255,否则总是返回 65535


4.3 Deep Sleep

http://wiki.jackslab.org/ESP8266_Sleep#Deep_Sleep

#define    __SET__DEEP_SLEEP__WAKEUP_NO_RF__    system_deep_sleep_set_option(4)
#define    __SET__DEEP_SLEEP__WAKEUP_NORMAL__   system_deep_sleep_set_option(1)

system_deep_sleep(100000);

During deep sleep, only RTC still working, so you can save some user data in RTC memory. Only "user data" area can be used by user

#define RTC_RAM_BASE	        0x60001000	// Size: 1024 bytes
#define RTC_MEM_BASE	        0x60001100
0x60001000	0x100	rtcb	RTC backup memory, see rtc_mem_backup
0x60001100	0x300	rtcmem	RTC semi-persistent memory, see system_rtc_mem_write

|-------- system data --------|-------- user data --------|
|         256 bytes           |          512 bytes        |
|      256/4 = 64 block       |          128 block        |

rtc time use the first 24 bytes of user data area

void system_deep_sleep_instant(uint32 time_in_us);

Notice: Seems like the system timer of WiFi is working when chip is in deep sleep, so you need to disable the all timers ...


4.4 Example

#define SENSOR_DATA_NUM 20
#define SENSOR_DATA_MEM_ADDR 120
#define INIT_MAGIC 0x7e7e55aa

typedef struct{
    uint32 init_flg;
    uint16 cnt;
    uint16 wifi_config;
    uint16 data[SENSOR_DATA_NUM];
}SENSOR_DATA_RTC_MEM;

SENSOR_DATA_RTC_MEM sensor_data;

void ICACHE_FLASH_ATTR data_func() {
// Read out the sensor data structure from RTC memory
system_rtc_mem_read( SENSOR_DATA_MEM_ADDR, &sensor_data, sizeof(SENSOR_DATA_RTC_MEM) );

// When the system powers on for the first time, the data in the rtc memory is random.
struct esp_platform_saved_param esp_param_t;
user_esp_platform_load_param(&esp_param_t);  // Stored in flash
// Load user params to check if the device was successfully registered to the server
// If it wasn't, it usually returns 255 (from the flash.)

if(sensor_data.init_flg!=INIT_MAGIC || sensor_data.cnt>SENSOR_DATA_NUM ) {
    // This case runs when we first power on or when it time to flush the RTC memory of old data.
    if(esp_param_t.activeflag!=1) {   // If registered & activated
        user_esp_platform_init();     // Router is not configured. Setup softAP. Wait for config. 
        user_webserver_init(SERVER_PORT);
    } else {
        // was connected! So we set init magic to exit the setup loop
        sensor_data.init_flg = INIT_MAGIC;
        sensor_data.cnt = 0;
        system_rtc_mem_write(SENSOR_DATA_MEM_ADDR, &sensor_data, sizeof(SENSOR_DATA_RTC_MEM));
        __SET__DEEP_SLEEP__WAKEUP_NO_RF__; 
        system_deep_sleep(100000); 
    }
} else { // This is where the measurements are made
    uint16 vdd_val = 0;
    if(sensor_data.cnt<0 || sensor_data.cnt>=SENSOR_DATA_NUM) 
        sensor_data.cnt=0; // range check and resets counter if needed

    /* Reads power supply voltage, byte 107 of init_data.bin should be set to 0xFF.
    *  Replace with your own code.*/
    sensor_data.data[sensor_data.cnt++] = (uint16)(phy_get_vdd33());
    system_rtc_mem_write( SENSOR_DATA_MEM_ADDR, &sensor_data, sizeof(SENSOR_DATA_RTC_MEM) );

    // Setup next sleep cycle
    if(sensor_data.cnt==SENSOR_DATA_NUM-1) { __SET__DEEP_SLEEP__WAKEUP_NORMAL__; }
    else { __SET__DEEP_SLEEP__WAKEUP_NO_RF__; }

    // Uploads or go to sleep
    if(sensor_data.cnt == SENSOR_DATA_NUM) { user_esp_platform_init(); }
    else { system_deep_sleep(SENSOR_DEEP_SLEEP_TIME); }
}
}


4.5 TX Power

函数:  
 void system_phy_set_max_tpw(uint8 max_tpw) 
功能:  
 设置 RF TX Power 最大值,单位:0.25dBm
参数:  
 uint8 max_tpw : RF Tx Power 的最大值,可参考 esp_init_data_default.bin(0 ~ 127byte)的第 34 byte (target_power_qdb_0) 设置,单位:0.25dBm,参数范围 [0, 82] 


函数:  
 void system_phy_set_tpw_via_vdd33(uint16 vdd33) 
功能:  
 根据改变的 VDD33 电压值,重新调整 RF TX Power,单位:1/1024 V 
注意:  
 在 TOUT 管脚悬空的情况下,VDD33 电压值可通过 system_get_vdd33 测量获得。
 在 TOUT 管脚接外部电路情况下,不可使用 system_get_vdd33 测量 VDD33 电压值。
参数:  
 uint16 vdd33 : 重新测量的 VDD33 值,单位:1/1024V,有效值范围:[1900, 3300] 



5 Debug 10.0.0.1

WAN 断了,路由就把所有的域名解析为 10.0.0.1 了。。。

部分特殊情形,网络繁忙的时候也会解析为 10.0.0.1。。。

Current firmware is user1.bin
Noduino version 2.0.0 Sun May 26 06:59:11 CST 2019 (Jack@mtgaga-surface) (gcc version 4.8.2 (GCC) )

Cold boot up or Need push data or realtime mode. Flag: 0x00000000, cnt: 9
fetch datapoint...
vbat = 3.46
mode : sta(5c:cf:7f:80:06:cb)
add if0

mjyun wan is running...
mjyun_wan_init: init...
scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 14
cnt 

connected with comcat, channel 11
dhcp client start...
WIFI_EVENT: connect to ssid comcat, channel 11
ip:192.168.1.174,mask:255.255.255.0,gw:192.168.1.1
WIFI_EVENT: ip:192.168.1.174,mask:255.255.255.0,gw:192.168.1.1
mjyun: restart all services, sta_ok
mjyun_wan_delete: delete
mjyun_wan_create: create
Platform: WIFI_STATION_OK
mjyun_wan_set_state: set state to 1
Platform: MJYUN_CONNECTING
MJYUN: MJYUN_CONNECTING 
mjyun_wan_check_ip: check product ID: [MKP2018102913]
mjyun_wan_check_ip: try distribution device
mjyun_wan_device_distribution: memory left=40864
hostname=api.noduino.org
port=80
method=POST
path=/dev/distribute
DNS request
http_raw_request: memory left=40792
http_raw_request: memory left=40496
http_raw_request: memory left=40224
DNS pending
mjyun_wan_device_distribution: url http://api.noduino.org/dev/distribute
mjyun_wan_device_distribution: body {"product_id":"MKP2018102913","device_id":"MKD650027282184"}
DNS found api.noduino.org 10.0.0.1
The ipaddr resolved by router is invalide!
state: 5 -> 0 (0)
rm 0
del if0
usl
WIFI_EVENT: disconnect from ssid comcat, reason 8
Platform: WIFI_STA_DISCONNECTED
mjyun: stop all services, try_ap_cache
mjyun_wan_delete: delete
mjyun_wan_set_state: set state to 0
MJYUN: MJYUN_CONNETING_AP 
WiFi AP is changing...
Current AP id is: 0
Try the cached WiFi AP id: 1
Try the cached WiFi AP id: 2
mjyun: start smartlink, smart
mjyun_wan_delete: delete
SC version: V2.5.4
del if0
usl
del if0
usl
Fatal exception 28(LoadProhibitedCause):
epc1=0x4000df2f, epc2=0x00000000, epc3=0x00000000, excvaddr=0x00000033, depc=0x00000000

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x60000020, len 4, room 16 
tail 4
���\0�8��n��>�r���n�b������l�r������I8����� ������r����


6 TODO

  • ADC 获取电池电压(小改硬件电路),电池电压数据上传
  • 太阳能充电支持
  • 动态开启/关闭 MQTT 20181101, http post 返回 {"mqtt":"disable"}
  • 低功耗优化
  • 夏天睡死,wake up cnt = 2/3
  • dns requst is 10.0.0.1
  • 短点续传
  • 电池电压过低 (<3V) 时候,以小时为单位延长 deep sleep 时间,给太阳能补电争取时间


7 Notes

Fluke 18B 毫安档:

  • 冷启动最高 85mA,75 ~ 60mA 常见,持续时间平均 8s 左右,这个时间有点长。。。
  • deep sleep 电流 1.7mA,移除 TL431 后,电流降为 65uA


  • boot_v1.5.bin: 从 deep sleep 醒来,有时 50/18, 40/17, 33/18, 30/18, 25/18, 21/18 mA,常见 18/18, 18/17 mA,持续 2s 左右
  • 周期 push 点:72/69/79/63/43 mA


  • boot_v1.5_low_power.bin: 从 deep sleep 醒来,有时 25/18, 23/18, 18/15, 18/16, 12/18, 18/10 mA, 常见 18/18 mA,持续 2s 左右
  • 周期 push 点:71/69/74/68/40 mA, 71/98/69/72 mA


2019/05/24:

Fluke 18B 微安档,实测睡眠电流 65uA 左右。。。


2019/05/27 OpenTemp:

  • iBee AP2112 as device power switch: deep sleep current 390uA
  • 移除 iBee AP2112 (dev pwr switch): deep sleep current 370uA


  • 移除另一个 iBee AP2112 (Vbat LDO): deep sleep current 40uA


  • 增加两个 AP2112 (Vbat LDO 和 dev pwr switch): deep sleep current 79uA
  • 移除其中的 dev pwr switch,deep sleep current 75uA,差别不大
  • 控温低于 250 度,又换了一个 AP2112 (Vbat LDO),依然 75uA。结论应该就是,使用 LDO,deep sleep 电流就得 75uA 左右,远超 ESP8266 的睡眠电流 20uA


8 NO RF

  • 硬件:Falcon v2.4 开发板,ESP-12F
  • 固件:examples/noduino/hello
void setup()
{
    serial_begin(115200);
    wifi_set_opmode(NULL_MODE);
}

void loop()
{
    serial_printf("Hello World!\r\n");
    delay(1500);
}
  • 90 mA 左右
  • 用 disable-rf 脚步处理后,依然是 90mA 左右,这个影响的应该是深睡眠唤醒后的功耗



9 Reference








个人工具
名字空间

变换
操作
导航
工具箱