查看Noduino OpenPlant的源代码
←
Noduino OpenPlant
跳转到:
导航
,
搜索
因为以下原因,你没有权限编辑本页:
您刚才请求的操作只有这个用户组中的用户才能使用:
用户
您可以查看并复制此页面的源代码:
== Overview == [[文件:OpenPlant-01.jpg | 500px]][[文件:OpenPlant-02.jpg | 504px]] <br><br> == 太阳能补电 == [[文件:Openplant-lowpower-01.jpg | 500px]] === 太阳能电池的 I-V特性 === 太阳能电池一般由 PN 结组成,PN 结中的光能 (光子) 通过导致电子和空穴的重新组合而产生电流。由于 PN 结的特性类似于二极管的特性,我们一般以下图中所示的电路作为太阳能电池特性的一个简化模型: [[文件:Solar-panel-model.jpg]] 电流源 Iph 产生的电流和太阳能电池上的光量度成正比。在没有负载连接的时候,几乎所有产生的电流都流过二极管 D,其正向电压决定着太阳能电池的开路电压 (Voc)。该电压会因各种类型太阳能电池的特性不同而有所差异。但是,对于大多数硅电池而言,这一<b>电压都在 0.5V 到 0.6V 之间</b>,这也是 PN 结二极管的正常正向电压。 在实际太阳能电池应用中,并联电阻 Rp 的泄漏电流很小,而 Rs 则会产生连接损耗。下图展示了太阳能电池在输出上的特性。由于串联电阻 Rs 的原因,电压会稍有下降。然而,有时如果通过内部二极管的电流太小,会导致偏置不够,并且穿过它的电压会随着负载电流的增加而急剧下降。最后,如果所有电流都只流过负载而不流过二极管,输出电压就会变为零。这个电流被称为太阳能电池的短路电流 Isc。Isc 和 Voc 都是定义太阳能工作性能的主要参数之一。 [[文件:Solar-panel-i-v.jpg | 700px]] <b>太阳能电池可认为是“电流限制”型电源,输出电压会随着输出电流的增加而降低,并在负载电流达到短路电流时降为零。 </b>其极端情况为: * 当输出电压为其最大数值 (Voc) 时,输出电流为零 * 当输出电流达到最大值 (Isc),但输出电压为零 曲线关系为: [[文件:Solar-panel-output.jpg | 700px]] 则输出功率也是动态变化的,其极值为最大功率点 (MPP)。 <b>实验记录出输出曲线,就能求得最大矩形面积的点 MPP,一般都会在输出特性曲线的下半部分的某个位置</b>,其确切位置会因入射光线和环境温度的不同而不同 太阳能电池的输出电流随光照强度的变化而变化,上下电流波动较大,一般不能直接给用电系统供电,需将能量先存储于电池中,然后通过电池为系统供电。 <br> === 电池板 === * 多晶太阳能电池板 4V/30mA,65mm x 28mm x 3mm * 多晶太阳能电池板 5.5V/60mA,60mm x 60mm x 3mm <br> === CN3083 === 芯片内部集成有 8 模数转换器,能够根据输入电压源的电流输出能力自动调节充电电流,用户不需要考虑最坏情况。当输入电压过低时,锁存,自动再充电;当输入电压掉电时,CN3083自动进入低功耗的睡眠模式,此时电池的电流消耗小于 3 uA 充电电流通过一个外部电阻设置。 内部固定的恒压充电电压为 4.2V,也可以通过一个外部电阻往高处调节。 热调制电路可以在器件的功耗比较大或者环境温度比较高的时候将芯片温度控制在安全范围内。 其它功能包括电池温度监控以及充电状态/充电结束状态指示等 <br> ==== 预充电状态 ==== 在充电周期的开始,如果电池电压 Kelvin 检测输入端 (FB) 的电压低于3V,充电器处于预充电状态,充电器以恒流充电模式充电电流的 10% 对电池进行充电。 <br> ==== 输入电压源限流模式 ==== 当 CN3083 输入电压源的电流输出能力(带负载能力)小于第 2 管脚的电阻 RISET 所设置的充电电流时,器件内部的 8 位 ADC 根据输入电压源的电流输出能力自动控制充电电流,此时实际充电电流可能小于所设置的充电电流,但是在保证 CN3083 第 4 管脚 VIN 的电压不低于最小工作电压的前提下,能够使得充电电流最大化 即当输出电流小于设置电流时,判断为光照不足,自动调节输出电流,优先保证电池板的输出电压。在这种模式下用户只要根据输入电压源的最大电流输出能力设置充电电流即可 <br> ==== 电池电压Kelvin检测 ==== CN3083 有一个电池电压 Kelvin检测输入端 (FB),此管脚通过芯片内部的精密电阻分压网络连接到恒压充电的误差放大器。 FB 管脚可以直接连接到电池的正极,这样可有效避免电池正极和 CN3083 的第 5 管脚 BAT 之间的寄生电阻(包括导线电阻,接触电阻等)对充电的影响。这些寄生电阻的存在会使充电器过早的进入恒压充电状态,延长充电时间,甚至使电池充不满,通过使用电池电压 Kelvin 检测可以解决这些问题。 如果将 CN3083 的电池电压 Kelvin 检测输入端 (FB) 悬空,那么CN3083一直处于预充电状态,充电电流为所设置的恒流充电电流的 1/10 <br> ==== 充电结束 ==== 在恒压充电状态,当施加在 CN3083 的第 4 管脚 VIN 的电压大于 4.45V,并且当充电电流小于所设置的恒流充电电流的 1/10 时,充电周期结束。 在输入电压源限流模式,即使充电电流小于所设置的恒流充电电流的 1/10,充电也将继续,不会结束。这样可以保证即使在输入电压源的电流输出能力很微弱的情况下,也能为电池充电。 <br> ==== 参考电路 ==== [[文件:CN3083-Sch.jpg]] <br> ==== Datasheet ==== [http://www.dfrobot.com.cn/images/upload/File/20180411142639cf3nql.pdf CN3083 Datasheet] <br> ==== 其他选择 ==== [http://www.consonance-elec.com/product-14.htm 太阳能充电管理芯片其他选择] <br> === CN3082 === CN3083 + 恒流后的维持电流模式 + 外部电阻设置维持电流 当 FB 管脚的电压上升到 2.445V 时,充电器结束恒流充电状态,进入维持充电状态,此时电池端对应的的恒流充电终止电压为: VBAT=2.445×(1+R3/R4) 此模式用于支持更多类型电池充电,比如:镍氢电池,磷酸铁锂电池和铅酸电池 [http://www.consonance-elec.com/pdf/%E6%8A%80%E6%9C%AF%E8%AF%B4%E6%98%8E%E4%B9%A6/DSC-CN3082.pdf CN3082 Datasheet] <br><br> == TODO == * <s>ADC 获取电池电压(小改硬件电路),电池电压数据上传</s> * <s>太阳能充电支持</s> * <s>动态开启/关闭 MQTT</s> 20181101, http post 返回 {"mqtt":"disable"} * 低功耗优化 * 电池电压过低 (<3V) 时候,自动关机(关闭电源芯片),给太阳能补电争取时间 <br> == 电池电压监控 == VBAT ------ 220K 1% ------ 100K 1% ------ GND | | ADC [[文件:Openplant-battery-monitor.jpg | 700px]] <source lang=cpp> 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; } </source> [[文件:Openplant-bat-curve.jpg | 700px]] <br><br> == 低功耗优化 == === Base === * <s>Transfer to use raw sdk</s> done * <s>Disable Ping</s> done * <s>Change the mode of mcp342x to One-Shot Conversion with 1 SPS</s> done <br><br> === 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''' <br> === Deep Sleep === http://wiki.jackslab.org/ESP8266_Sleep#Deep_Sleep <source lang=cpp> #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 |-------- system data --------|-------- user data --------| | 256 bytes | 512 bytes | </source> <br> === 批量 POST 数据 === <source lang=cpp> SENSOR_DATA_RTC_MEM sensor_data ; SENSOR_DATA_RTC_MEM* ICACHE_FLASH_ATTR get_sensor_data() { return &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); } } } </source> <br><br> ==Reference == * http://www.gongkong.com/advanced/ShowPaper.aspx?id=2010042110265100006 * [[ESP8266 Sleep]] * WiFi 低功耗传感器示例: https://github.com/EspressifSystems/low_power_voltage_measurement * https://github.com/EspressifSystems/low_power_voltage_measurement/wiki <br><br> <br><br><br><br>
返回到
Noduino OpenPlant
。
个人工具
登录
名字空间
页面
讨论
变换
查看
阅读
查看源代码
查看历史
操作
搜索
导航
首页
社区专页
新闻动态
最近更改
随机页面
帮助
工具箱
链入页面
相关更改
特殊页面