static THD_FUNCTION(m3pyro_continuity_thd, arg) { (void)arg; while(true) { adcsample_t sampbuf[5]; adcStart(&ADCD1, NULL); msg_t result = adcConvert(&ADCD1, &adc_grp, sampbuf, 1); adcStop(&ADCD1); if(result != MSG_OK) { m3status_set_error(M3PYRO_COMPONENT_CONTINUITY, M3PYRO_ERROR_ADC); chThdSleepMilliseconds(500); continue; } uint8_t continuities[4]; continuities[0] = adc_to_resistance(sampbuf[0]); continuities[1] = adc_to_resistance(sampbuf[1]); continuities[2] = adc_to_resistance(sampbuf[2]); continuities[3] = adc_to_resistance(sampbuf[3]); can_send(CAN_MSG_ID_M3PYRO_CONTINUITY, false, continuities, sizeof(continuities)); uint8_t supply; supply = adc_to_voltage(sampbuf[4]); can_send(CAN_MSG_ID_M3PYRO_SUPPLY_STATUS, false, &supply, 1); m3status_set_ok(M3PYRO_COMPONENT_CONTINUITY); chThdSleepMilliseconds(500); } }
static void rk29_adc_battery_timer_work(struct work_struct *work) { struct tm tm; static int fd_log = -1; struct rk30_adc_battery_platform_data *pdata = gBatteryData->pdata; rk29_adc_battery_status_samples(gBatteryData); if (poweron_check) { poweron_check = 0; rk29_adc_battery_poweron_capacity_check(); } rk29_adc_battery_voltage_samples(gBatteryData); rk29_adc_battery_capacity_samples(gBatteryData); /*update battery parameter after adc and capacity has been changed*/ if(gBatteryData->bat_change) { gBatteryData->bat_change = 0; rk29_adc_battery_put_capacity(gBatteryData->bat_capacity); power_supply_changed(&rk29_battery_supply); } if (rk29_battery_dbg_level) { if (++AdcTestCnt >= 20) { char buf[256] = {0}; time_to_tm(get_seconds(), 0, &tm); AdcTestCnt = 0; #if SAVE_BAT_LOG if (fd_log < 0) { fd_log = sys_open("/data/local/bat.log", O_CREAT | O_APPEND | O_RDWR, 0); printk("create /data/local/bat.log, fd_log = %d\n", fd_log); } else { sprintf(buf, "[%02d:%02d:%02d], bat_status = %d, RealAdc = %d, RealVol = %d, gBatVol = %d, gBatCap = %d, RealCapacity = %d,\ dischargecnt = %d, chargecnt = %d, dc_det = %d, charge_ok = %d\n", tm.tm_hour, tm.tm_min, tm.tm_sec, gBatteryData->bat_status, AdcTestvalue, adc_to_voltage(AdcTestvalue), gBatteryData->bat_voltage, gBatteryData->bat_capacity, capacitytmp, gBatCapacityDisChargeCnt, gBatCapacityChargeCnt, gpio_get_value(pdata->dc_det_pin), gpio_get_value(pdata->charge_ok_pin)); int ret = sys_write(fd_log, (const char __user *)buf, strlen(buf)); printk("undate charge info, ret = %d, len=%d\n", ret, strlen(buf)); } #endif printk("Status = %d, RealAdcVal = %d, RealVol = %d,gBatVol = %d, gBatCap = %d, RealCapacity = %d, dischargecnt = %d, chargecnt = %d\n", gBatteryData->bat_status, AdcTestvalue, adc_to_voltage(AdcTestvalue), gBatteryData->bat_voltage, gBatteryData->bat_capacity, capacitytmp, gBatCapacityDisChargeCnt, gBatCapacityChargeCnt); } }
static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat) { int value; int i,*pStart = bat->adc_samples, num = 0; int level = rk30_adc_battery_get_charge_level(bat); value = bat->adc_val; adc_async_read(bat->client); *pSamples++ = adc_to_voltage(value); bat->bat_status_cnt++; if (bat->bat_status_cnt > NUM_VOLTAGE_SAMPLE) bat->bat_status_cnt = NUM_VOLTAGE_SAMPLE + 1; num = pSamples - pStart; if (num >= NUM_VOLTAGE_SAMPLE){ pSamples = pStart; num = NUM_VOLTAGE_SAMPLE; } value = 0; for (i = 0; i < num; i++){ value += bat->adc_samples[i]; } bat->bat_voltage = value / num; /* Check limits */ if(1 == level){ if(bat->bat_voltage >= batt_table[BATT_NUM-1].charge_vol + 10) bat->bat_voltage = batt_table[BATT_NUM-1].charge_vol + 10; else if(bat->bat_voltage <= batt_table[0].charge_vol - 10) bat->bat_voltage = batt_table[0].charge_vol - 10; } else{ if(bat->bat_voltage >= batt_table[BATT_NUM-1].dis_charge_vol + 10) bat->bat_voltage = batt_table[BATT_NUM-1].dis_charge_vol + 10; else if(bat->bat_voltage <= batt_table[0].dis_charge_vol - 10) bat->bat_voltage = batt_table[0].dis_charge_vol - 10; } }
static void rk2918_get_bat_voltage(struct rk2918_battery_data *bat) { int value; int i,*pSamp,*pStart = &gBatVoltageSamples[0],num = 0; int temp[2] = {0,0}; dprint("func=%s, line=%d :\n", __func__, __LINE__); value = gBatteryData->adc_val; AdcTestvalue = value; adc_async_read(gBatteryData->client); //*pSamples++ = (value * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R); *pSamples++ = adc_to_voltage(value); num = pSamples - pStart; if (num >= NUM_VOLTAGE_SAMPLE) { pSamples = pStart; gFlagLoop = 1; } if (gFlagLoop == 1) { num = NUM_VOLTAGE_SAMPLE; } value = 0; for (i = 0; i < num; i++) { value += gBatVoltageSamples[i]; } gBatVoltage = value / num; //gBatVoltage = (value * BAT_2V5_VALUE * 2) / 1024; /*消除毛刺电压*/ if(gBatVoltage >= BATT_MAX_VOL_VALUE + 10) gBatVoltage = BATT_MAX_VOL_VALUE + 10; else if(gBatVoltage <= BATT_ZERO_VOL_VALUE - 10) gBatVoltage = BATT_ZERO_VOL_VALUE - 10; //充放电状态变化时,开始计数 if (++gBatStatusChangeCnt > NUM_VOLTAGE_SAMPLE) gBatStatusChangeCnt = NUM_VOLTAGE_SAMPLE + 1; }
static void rk2918_low_battery_check(void) { int i; int tmp = 0; dprint("func=%s, line=%d :\n", __func__, __LINE__); for (i = 0; i < 100; i++) { tmp += adc_sync_read(gBatteryData->client); mdelay(1); } tmp = tmp / 100; //tmp = (tmp * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R); tmp = adc_to_voltage(tmp); rk2918_get_charge_status(); gBatCapacity = rk2918_get_bat_capacity_raw(tmp); if (gBatCapacity == 0) gBatCapacity = 1; printk("rk2918_low_battery_check: gBatVoltage = %d, gBatCapacity = %d\n", gBatVoltage, gBatCapacity); if (gBatVoltage <= BATT_ZERO_VOL_VALUE + 50) { printk("low battery: powerdown\n"); gpio_direction_output(POWER_ON_PIN, GPIO_LOW); tmp = 0; while(1) { if(gpio_get_value(POWER_ON_PIN) == GPIO_HIGH) { gpio_set_value(POWER_ON_PIN,GPIO_LOW); } mdelay(5); if (++tmp > 50) break; } } gpio_direction_output(POWER_ON_PIN, GPIO_HIGH); }
static void rk29_adc_battery_voltage_samples(struct rk29_adc_battery_data *bat) { int value; int i,*pStart = bat->adc_samples, num = 0; value = bat->adc_val; AdcTestvalue = value; adc_async_read(bat->client); *pSamples++ = adc_to_voltage(value); bat->bat_status_cnt++; if (bat->bat_status_cnt > NUM_VOLTAGE_SAMPLE) bat->bat_status_cnt = NUM_VOLTAGE_SAMPLE + 1; num = pSamples - pStart; if (num >= NUM_VOLTAGE_SAMPLE) { pSamples = pStart; gFlagLoop = 1; } if (gFlagLoop == 1) { num = NUM_VOLTAGE_SAMPLE; } value = 0; for (i = 0; i < num; i++) { value += bat->adc_samples[i]; } bat->bat_voltage = value / num; /*消除毛刺电压*/ if(bat->bat_voltage >= BATT_MAX_VOL_VALUE + 10) bat->bat_voltage = BATT_MAX_VOL_VALUE + 10; else if(bat->bat_voltage <= BATT_ZERO_VOL_VALUE - 10) bat->bat_voltage = BATT_ZERO_VOL_VALUE - 10; }
/* No charge_ok_pin available */ if (bat->bat_capacity == 100){ if (bat->bat_status != POWER_SUPPLY_STATUS_FULL){ bat->bat_status = POWER_SUPPLY_STATUS_FULL; bat->bat_change = 1; } } else{ bat->bat_status = POWER_SUPPLY_STATUS_CHARGING; } } else{ // pin of charge_ok_pin if (gpio_get_value(pdata->charge_ok_pin) != pdata->charge_ok_level){ bat->full_times = 0; bat->bat_status = POWER_SUPPLY_STATUS_CHARGING; } else{ bat->full_times++; if (bat->full_times >= NUM_CHARGE_FULL_DELAY_TIMES) { bat->full_times = NUM_CHARGE_FULL_DELAY_TIMES + 1; } if ((bat->full_times >= NUM_CHARGE_FULL_DELAY_TIMES) && (bat->bat_capacity >= 99)){ if (bat->bat_status != POWER_SUPPLY_STATUS_FULL){ bat->bat_status = POWER_SUPPLY_STATUS_FULL; bat->bat_capacity = 100; bat->bat_change = 1; } } else{ bat->bat_status = POWER_SUPPLY_STATUS_CHARGING; } } } } return charge_level; } #if 0 /* Astralix */ static int rk_adc_voltage(int value) { int voltage; int ref_voltage; //reference_voltage int pullup_res; int pulldown_res; ref_voltage = gBatteryData ->pdata->reference_voltage; pullup_res = gBatteryData ->pdata->pull_up_res; pulldown_res = gBatteryData ->pdata->pull_down_res; if(ref_voltage && pullup_res && pulldown_res){ voltage = ((value * ref_voltage * (pullup_res + pulldown_res)) / (1024 * pulldown_res)); }else{ voltage = adc_to_voltage(value); } return voltage; }
static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat) { int value; int i,*pStart = bat->adc_samples, num = 0; int level = rk30_adc_battery_get_charge_level(bat); value = bat->adc_val; adc_async_read(bat->client); *pSamples++ = adc_to_voltage(value); bat->bat_status_cnt++; if (bat->bat_status_cnt > NUM_VOLTAGE_SAMPLE) bat->bat_status_cnt = NUM_VOLTAGE_SAMPLE + 1; num = pSamples - pStart; if (num >= NUM_VOLTAGE_SAMPLE){ pSamples = pStart; num = NUM_VOLTAGE_SAMPLE; } value = 0; for (i = 0; i < num; i++){ value += bat->adc_samples[i]; } bat->bat_voltage = value / num; /*消除毛刺电压*/ if(battery_test_flag == 0) { if(1 == level){ if(bat->bat_voltage >= batt_table[2*BATT_NUM +5]+ 10) bat->bat_voltage = batt_table[2*BATT_NUM +5] + 10; else if(bat->bat_voltage <= batt_table[BATT_NUM +6] - 10) bat->bat_voltage = batt_table[BATT_NUM +6] - 10; } else{ if(bat->bat_voltage >= batt_table[BATT_NUM +5]+ 10) bat->bat_voltage = batt_table[BATT_NUM +5] + 10; else if(bat->bat_voltage <= batt_table[6] - 10) bat->bat_voltage = batt_table[6] - 10; } }else if(battery_test_flag == 2) /**************************************************/ { if(batt_table[3] == 0) { if(bat->bat_voltage < 3400) { //printk("gSecondsCnt=%ld,get_seconds()=%ld,(get_seconds() - gSecondsCnt)=%ld-------------------1\n",gSecondsCnt,get_seconds(),(get_seconds() - gSecondsCnt)); if((get_seconds() - gSecondsCnt) > 30) { gSecondsCnt = get_seconds(); //printk("gSecondsCnt=%ld,gVoltageCnt=%d,(gVoltageCnt - bat->bat_voltage)=%d,bat->bat_voltage=%d-------------------2\n",gSecondsCnt,gVoltageCnt,(gVoltageCnt - bat->bat_voltage),bat->bat_voltage); if((gVoltageCnt - bat->bat_voltage) > 15) { //gVoltageCnt = bat->bat_voltage; //printk("gVoltageCnt=%d-------------------3\n",gVoltageCnt); strncpy(gDischargeFlag, "off" ,3); } gVoltageCnt = bat->bat_voltage; } } if(bat->bat_voltage < 3400) { bat->bat_voltage = 3400; } } else { if(bat->bat_voltage < 6800) { //printk("gSecondsCnt=%ld,get_seconds()=%ld,(get_seconds() - gSecondsCnt)=%ld-------------------1\n",gSecondsCnt,get_seconds(),(get_seconds() - gSecondsCnt)); if((get_seconds() - gSecondsCnt) > 30) { gSecondsCnt = get_seconds(); //printk("gSecondsCnt=%ld,gVoltageCnt=%d,(gVoltageCnt - bat->bat_voltage)=%d,bat->bat_voltage=%d-------------------2\n",gSecondsCnt,gVoltageCnt,(gVoltageCnt - bat->bat_voltage),bat->bat_voltage); if((gDoubleVoltageCnt - bat->bat_voltage) > 30) { //gVoltageCnt = bat->bat_voltage; //printk("gVoltageCnt=%d-------------------3\n",gVoltageCnt); strncpy(gDischargeFlag, "off" ,3); } gDoubleVoltageCnt =bat->bat_voltage; } } if(bat->bat_voltage < 6800) { bat->bat_voltage = 6800; } } } /****************************************************/ }
static void rk2918_battery_timer_work(struct work_struct *work) { rk2918_get_bat_status(gBatteryData); rk2918_get_bat_health(gBatteryData); rk2918_get_bat_present(gBatteryData); rk2918_get_bat_voltage(gBatteryData); //to prevent gBatCapacity be changed sharply if (gBatCapacity < 0) { gBatCapacity = 0; } else { if (gBatCapacity > 100) { gBatCapacity = 100; } } rk2918_get_bat_capacity(gBatteryData); if (rk29_battery_dbg_level) { if (++AdcTestCnt >= 20) { AdcTestCnt = 0; printk("\nchg_ok_level =%d, chg_ok= %d, gBatStatus = %d, adc_val = %d, TrueBatVol = %d,gBatVol = %d, gBatCap = %d, captmp = %d, sec = %lu, time_chg_flag = %d, first_flag = %d\n", gBatteryData->charge_ok_level, gpio_get_value(gBatteryData->charge_ok_pin), gBatStatus, AdcTestvalue, adc_to_voltage(AdcTestvalue), gBatVoltage, gBatCapacity, capacitytmp, batteryspendcnt, time_chg_flag, first_flag); } } /*update battery parameter after adc and capacity has been changed*/ if(((gBatStatus != gBatLastStatus) || (gBatPresent != gBatLastPresent) || (gBatCapacity != gBatLastCapacity))&&(suspend_flag==0)) { //for debug if (rk29_battery_dbg_level) { char _tmp_buf[250]; int buf_len = 0; struct file* fp; sprintf(_tmp_buf, "gBatStatus = %d, adc_val = %d, TrueBatVol = %d,gBatVol = %d, gBatCap = %d, captmp = %d, sec = %lu, inter_sec = %lu, time_chg_flag = %d, first_flag = %d\n", gBatStatus, AdcTestvalue, ((AdcTestvalue * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R)), gBatVoltage, gBatCapacity, capacitytmp, batteryspendcnt, batteryspendcnt - last_batteryspendcnt, time_chg_flag, first_flag); buf_len = strlen(_tmp_buf); fp = filp_open(BATT_DBG_FILE,O_RDWR | O_APPEND | O_CREAT, 0); if(IS_ERR(fp)) { printk("bryan---->open file /data/bat_dbg_record.dat failed\n"); } else { kernel_write(fp, _tmp_buf, buf_len ,buf_offset); filp_close(fp,NULL); buf_offset += buf_len; } last_batteryspendcnt = batteryspendcnt; } gBatLastStatus = gBatStatus; gBatLastPresent = gBatPresent; gBatLastCapacity = gBatCapacity; power_supply_changed(&gBatteryData->battery); } }
static int rk2918_battery_resume_get_Capacity(int deltatime) { int i; int tmp = 0; int capacity = 0; for (i = 0; i < 20; i++) { tmp += adc_sync_read(gBatteryData->client); mdelay(1); } tmp = tmp / 20; //tmp = (tmp * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R); tmp = adc_to_voltage(tmp); capacity = rk2918_get_bat_capacity_raw(tmp); //if last status is charging FULL, will return 100 if(last_BatChargeStatus == POWER_SUPPLY_STATUS_FULL) return 100; //if last status is charging , and now still charging if ((gBatChargeStatus == 1) && (last_BatChargeStatus == 1)) { /* if (deltatime > (100 - gBatCapacity) * CHARGE_MIN_SECOND) deltatime = (100 - gBatCapacity) * CHARGE_MIN_SECOND; if (capacity > gBatCapacity + (deltatime / CHARGE_MIN_SECOND)) //采样电池容量偏差较大,将容量拉回 { capacity = gBatCapacity + (deltatime / CHARGE_MIN_SECOND); } */ // if((gBatCapacity > 80)) { capacity = gBatCapacity + deltatime/CHARGE_MID_SECOND; } else { /*some battery cannot arrive to 4.1V when charging full*/ if((deltatime > (100 - gBatCapacity) * CHARGE_MID_SECOND)) { capacity = 99; if (rk29_battery_dbg_level) printk("0000rk2918_battery_resume: last_BatChargeStatus: %d, gBatChargeStatus: %d, gBatVoltage = %d, gBatCapacity = %d, deltatime = %d, capacity = %d\n", last_BatChargeStatus, gBatChargeStatus, gBatVoltage, gBatCapacity, deltatime, capacity); if (gBatStatus == POWER_SUPPLY_STATUS_FULL) { capacity = 100; } return capacity; } /*if battery is not full after long charging*/ if((capacity > 80)) { if(capacity < gBatCapacity + deltatime/CHARGE_MID_SECOND) capacity = gBatCapacity + deltatime/CHARGE_MID_SECOND; if(capacity >= 100) capacity = 99; if (gBatStatus == POWER_SUPPLY_STATUS_FULL) { capacity = 100; } if (rk29_battery_dbg_level) printk("11111rk2918_battery_resume: last_BatChargeStatus: %d, gBatChargeStatus: %d, gBatVoltage = %d, gBatCapacity = %d, deltatime = %d, capacity = %d\n", last_BatChargeStatus, gBatChargeStatus, gBatVoltage, gBatCapacity, deltatime, capacity); return capacity; } if(capacity > gBatCapacity) { if((capacity-gBatCapacity)>15) gBatCapacity = capacity; else { if(gBatCapacity > 20) capacity=gBatCapacity; else gBatCapacity =(gBatCapacity + capacity)/2; } } else if (capacity < gBatCapacity) { if((gBatCapacity - capacity)>10) gBatCapacity = capacity; else capacity=gBatCapacity ; } } if (capacity >= 100) capacity = 99; } else { /* if (deltatime > gBatCapacity * DISCHARGE_MIN_SECOND) deltatime = gBatCapacity * DISCHARGE_MIN_SECOND; if (capacity < gBatCapacity - (deltatime / DISCHARGE_MIN_SECOND)) //采样电池容量偏差较大,将容量拉回 { capacity = gBatCapacity - (deltatime / DISCHARGE_MIN_SECOND); } */ if (rk29_battery_dbg_level) printk("333rk2918_battery_resume: last_BatChargeStatus: %d, gBatChargeStatus: %d, gBatVoltage = %d, gBatCapacity = %d, deltatime = %d, capacity = %d\n", last_BatChargeStatus, gBatChargeStatus, gBatVoltage, gBatCapacity, deltatime, capacity); /*to ensure battery show 100% after long charging during sleep and then pug out charger*/ if((deltatime > (100 - gBatCapacity) * CHARGE_MID_SECOND) && (last_BatChargeStatus == 1)) { if(capacity < 99) capacity = 99; if(capacity >= 100) capacity = 100; return capacity; } if (capacity < gBatCapacity) { if((gBatCapacity - capacity)>10) gBatCapacity = capacity; else capacity=gBatCapacity ; } else if (capacity > gBatCapacity) { if((capacity-gBatCapacity)>15) gBatCapacity = capacity; else capacity=gBatCapacity ; } } if (capacity == 0) capacity = 1; if (capacity >= 100) capacity = 100; if (gBatStatus == POWER_SUPPLY_STATUS_FULL) { capacity = 100; } if (rk29_battery_dbg_level) printk("rk2918_battery_resume: last_BatChargeStatus: %d, gBatChargeStatus: %d, gBatVoltage = %d, gBatCapacity = %d, deltatime = %d, ktmietmp.tv.sec = %lu, capacity = %d\n", last_BatChargeStatus, gBatChargeStatus, gBatVoltage, gBatCapacity, deltatime, batteryspendcnt, capacity); return capacity; }
static int rk2918_battery_load_capacity(void) { int i; int tmp = 0; int loadcapacity = 0; int truecapacity = 0; char value[11]; static char lastthree[6]= {0}; char* p = value; struct file* fp = filp_open(BATT_FILENAME,O_RDONLY,0); //get true capacity for (i = 0; i < 20; i++) { tmp += adc_to_voltage(adc_sync_read(gBatteryData->client)); mdelay(1); } tmp = tmp / 20; lastlost = tmp; truecapacity = rk2918_get_bat_capacity_raw(tmp); if(IS_ERR(fp)) { printk("bryan---->open file /data/bat_last_capacity.dat failed\n"); printk("truecapacity = %d\n", truecapacity); if(truecapacity>=100) truecapacity = 100; if(truecapacity==0) truecapacity=1; openfailflag = 1; if (openfailcount <= 5) { lastthree[openfailcount-1] = truecapacity; if (openfailcount == 1) { tmp = 0; for (i=0;i<5;i++) { tmp += lastthree[4-i]; printk("%s...............%d\n",__func__,tmp); } truecapacity = tmp/5; printk("%s...............%d\n",__func__,tmp); } } return truecapacity; } else { openfailflag = 0; openfailcount = 0; } kernel_read(fp,0,value,10); filp_close(fp,NULL); value[10]=0; while(*p) { if(*p==0x0d) { *p=0; break; } p++; } sscanf(value,"%d",&loadcapacity); printk("bryan---->loadcapacity = %d, truecapacity = %d\n",loadcapacity, truecapacity); if ((loadcapacity <= 0) || (loadcapacity > 100)) { loadcapacity = truecapacity; } //如果从文件中读取的电压比实际的高很多的话,说明是长时间放置导致放电 if (loadcapacity > truecapacity) { if (loadcapacity - truecapacity > 20) { loadcapacity = truecapacity; } } else { if ( ((truecapacity-loadcapacity) >= 20)) { if (truecapacity < 30) { if (loadcapacity < 10) { loadcapacity = truecapacity/2; } } else { loadcapacity = truecapacity; } } } if (loadcapacity <= 0) { loadcapacity = 1; } if (loadcapacity >= 100) { loadcapacity = 100; } return loadcapacity; }