{
 "metadata": {
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  },
  "orig_nbformat": 4,
  "kernelspec": {
   "name": "python3",
   "display_name": "Python 3.8.10 64-bit"
  },
  "interpreter": {
   "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2,
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 27,
   "source": [
    "# Current sense aplifier preliminary design \n",
    "\n",
    "supply_voltage = 4.2\n",
    "max_current = 2.0\n",
    "acceptable_power_loss = 0.1 #watts\n",
    "amp_ratios = [50,100,200]\n",
    "sense_voltage = 3.3\n",
    "\n",
    "adc_resolution = 4096\n",
    "divider_R1 = 100 # kilo-ohms\n",
    "\n",
    "max_power = supply_voltage * max_current\n",
    "\n",
    "acceptable_voltage_drop = acceptable_power_loss / supply_voltage\n",
    "print(\"Acceptable voltage drop: {}V\".format(round(acceptable_voltage_drop,2)))\n",
    "power_loss_percentage = acceptable_power_loss/max_power*100\n",
    "print(\"Power loss percentage: {}%\".format(round(power_loss_percentage,2)))\n",
    "\n",
    "amp_ratios.sort()\n",
    "\n",
    "print(\"--------------- Full - range ---------------\")\n",
    "for ratio in amp_ratios:\n",
    "    ideal_resistor = supply_voltage / ratio / max_current\n",
    "    power_loss = ideal_resistor * max_current**2\n",
    "\n",
    "    print(\"Ideal resistor: {}R\".format(ideal_resistor))\n",
    "    print(\"Power loss: {}W\".format(power_loss))\n",
    "    print(\"--------------------------------------------\")\n",
    "\n",
    "if sense_voltage < supply_voltage:\n",
    "    divider_R2 = round((sense_voltage * divider_R1) / (supply_voltage - sense_voltage),3)\n",
    "    print(\"Output voltage divider: R1 = {} kΩ, R2 = {} kΩ\".format(divider_R1,divider_R2))\n",
    "\n",
    "max_output_voltage = min(supply_voltage, supply_voltage)\n",
    "resolution = round(max_current/adc_resolution*1000,2)\n",
    "print(\"Resolution: {}mA\".format(resolution))\n",
    "\n",
    "print(\"---------------- Acceptable ----------------\")\n",
    "acceptable_resistor = acceptable_voltage_drop/max_current\n",
    "power_loss = acceptable_resistor * max_current**2\n",
    "\n",
    "ideal_ratio = None\n",
    "for ratio in amp_ratios:\n",
    "    if acceptable_voltage_drop * ratio < supply_voltage:\n",
    "        ideal_ratio = ratio\n",
    "    else:\n",
    "        break\n",
    "\n",
    "max_output_voltage = acceptable_voltage_drop * ideal_ratio\n",
    "print(\"Maximal output voltage: {}V\".format(max_output_voltage))\n",
    "\n",
    "if sense_voltage < max_output_voltage:\n",
    "    divider_R2 = round((sense_voltage * divider_R1) / (max_output_voltage - sense_voltage),3)\n",
    "    print(\"Output voltage divider: R1 = {} kΩ, R2 = {} kΩ\".format(divider_R1,divider_R2))\n",
    "\n",
    "resolution = round(max_current/adc_resolution*1000,2)\n",
    "\n",
    "print(\"Ideal ratio: {}\".format(ideal_ratio))\n",
    "print(\"Ideal resistor: {}R\".format(acceptable_resistor))\n",
    "print(\"Power loss: {}W\".format(power_loss))\n",
    "print(\"Resolution: {}mA\".format(resolution))"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Acceptable voltage drop: 0.02V\n",
      "Power loss percentage: 1.19%\n",
      "--------------- Full - range ---------------\n",
      "Ideal resistor: 0.042R\n",
      "Power loss: 0.168W\n",
      "--------------------------------------------\n",
      "Ideal resistor: 0.021R\n",
      "Power loss: 0.084W\n",
      "--------------------------------------------\n",
      "Ideal resistor: 0.0105R\n",
      "Power loss: 0.042W\n",
      "--------------------------------------------\n",
      "Output voltage divider: R1 = 100 kΩ, R2 = 366.667 kΩ\n",
      "Resolution: 0.49mA\n",
      "---------------- Acceptable ----------------\n",
      "Maximal output voltage: 2.380952380952381V\n",
      "Ideal ratio: 100\n",
      "Ideal resistor: 0.011904761904761904R\n",
      "Power loss: 0.047619047619047616W\n",
      "Resolution: 0.49mA\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "source": [
    "# Current sense aplifier design evaluating\n",
    "\n",
    "supply_voltage = 2.8\n",
    "sense_voltage = 3.3\n",
    "sense_resistor = 0.01\n",
    "amp_ratio = 50\n",
    "divider_R1  = 100 # kilo-ohms\n",
    "selected_R2 = 270 # kilo-ohms\n",
    "\n",
    "adc_resolution = 4096\n",
    "\n",
    "max_current = supply_voltage / sense_resistor / amp_ratio\n",
    "power_disipation = sense_resistor * max_current**2\n",
    "voltage_drop = sense_resistor * max_current\n",
    "resolution = round(max_current/adc_resolution*1000,3)\n",
    "\n",
    "\n",
    "print(\"Maximal current: {}A\".format(round(max_current,2)))\n",
    "print(\"Maximal power disipation: {}W\".format(round(power_disipation,2)))\n",
    "print(\"Maximal voltage drop: {}V\".format(round(voltage_drop,2)))\n",
    "\n",
    "if sense_voltage > supply_voltage:\n",
    "    resolution *= 1 / (supply_voltage/sense_voltage)\n",
    "\n",
    "print(\"Resolution: {} mA\".format(round(resolution,2)))\n",
    "\n",
    "if sense_voltage < supply_voltage:\n",
    "    divider_R2 = round((sense_voltage * divider_R1) / (supply_voltage - sense_voltage),2)\n",
    "    print(\"Output voltage divider: R1 = {} kΩ, R2 = {} kΩ\".format(divider_R1,divider_R2))\n",
    "    divider_leakage = supply_voltage / ((divider_R1 + divider_R2)*1000)\n",
    "    print(\"Maximum divider leakage: {} uA\".format(round(divider_leakage*1000000),2))\n",
    "\n",
    "print(\"---------------- Selected divider ----------------\")\n",
    "maximum_divider_voltage = supply_voltage * (selected_R2 / (selected_R2 + divider_R1))\n",
    "print(\"Maximum divider voltage: {} V\".format(round(maximum_divider_voltage,2)))\n",
    "resolution *= 1 / (maximum_divider_voltage/sense_voltage)\n",
    "print(\"Resolution: {} mA\".format(round(resolution,2)))"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Maximal current: 2.8A\n",
      "Maximal power disipation: 0.08W\n",
      "Maximal voltage drop: 0.03V\n",
      "Resolution: 0.81 mA\n",
      "---------------- Selected divider ----------------\n",
      "Maximum divider voltage: 2.04 V\n",
      "Resolution: 1.3 mA\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "source": [
    "# Battery heating wire calculator\n",
    "import math\n",
    "\n",
    "bat_diameter = 21 # in mm\n",
    "heating_power = 2 # watts\n",
    "voltage = 3.7\n",
    "wire_resistance = 5.5 # per meter\n",
    "\n",
    "wrap_length = bat_diameter * math.pi / 1000\n",
    "current = heating_power / voltage\n",
    "resistance = voltage / current\n",
    "length = resistance / wire_resistance\n",
    "wraps = length / wrap_length\n",
    "\n",
    "print(\"Length: {}\".format(length))\n",
    "print(\"Wraps:  {}\".format(wraps))"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Length: 1.2445454545454548\n",
      "Wraps:  18.86433914223418\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "source": [
    "# LTC4231\n",
    "\n",
    "# Voltage settings\n",
    "undervoltage_rising = 3\n",
    "undervoltage_falling = 2.9\n",
    "overvoltage_falling = 4.4\n",
    "input_voltage = 3.7\n",
    "\n",
    "# Design parameters\n",
    "resistance_total = 2000000\n",
    "overcurrent_threshold = 5\n",
    "soa_time = 0.0005\n",
    "\n",
    "# Sence voltage constants from LTC4231 datasheet\n",
    "sense_voltage_slow = 0.05\n",
    "sense_voltage_min  = 0.065\n",
    "sense_voltage_fast = 0.08\n",
    "sense_voltage_max  = 0.09\n",
    "\n",
    "R4 = (0.795/overvoltage_falling) * resistance_total\n",
    "R3 = ((overvoltage_falling/undervoltage_rising) - 1) * R4\n",
    "R2 = ((undervoltage_rising/undervoltage_falling) - 1) * (overvoltage_falling/undervoltage_rising) * R4\n",
    "R1 = ((overvoltage_falling/0.795) - 1) * R4 - R3 - R2\n",
    "\n",
    "print(\"R4 value = {}k\".format(round(R4/1000)))\n",
    "print(\"R3 value = {}k\".format(round(R3/1000)))\n",
    "print(\"R2 value = {}k\".format(round(R2/1000)))\n",
    "print(\"R1 value = {}k\".format(round(R1/1000)))\n",
    "\n",
    "divider_leakage = input_voltage/(R1 + R2 + R3 + R4)\n",
    "sense_resistor = sense_voltage_slow/overcurrent_threshold\n",
    "current_limit_fast = sense_voltage_fast / sense_resistor\n",
    "sense_resistor_power = sense_resistor * current_limit_fast**2\n",
    "current_limit_max = sense_voltage_max/sense_resistor\n",
    "\n",
    "print(\"Divider leakage = {} uA\".format(divider_leakage*1000000))\n",
    "print(\"Sensing resistor = {} mR\".format(sense_resistor*1000))\n",
    "print(\"Sensing resistor power dissipation = {} W\".format(sense_resistor_power))\n",
    "print(\"Worst case current = {} A\".format(current_limit_max))\n",
    "\n",
    "load_capacitor_charge = (0.0001 * input_voltage) / (sense_voltage_min / sense_resistor)\n",
    "mosfet_dissipation = input_voltage * current_limit_max\n",
    "overcurrent_triptime = (soa_time - load_capacitor_charge)/4 + load_capacitor_charge\n",
    "timer_capacitor = overcurrent_triptime/input_voltage\n",
    "\n",
    "print(\"OC timer charge = {} ms\".format(round(load_capacitor_charge*1000,2)))\n",
    "print(\"MOSFET power dissipation = {} W\".format(round(mosfet_dissipation,2)))\n",
    "print(\"Time to OC protection trip = {} ms\".format(round(overcurrent_triptime*1000,2)))\n",
    "print(\"Timer capacitor C_T value = {} nF\".format(round(timer_capacitor*1000000,2)))"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "R4 value = 361k\n",
      "R3 value = 169k\n",
      "R2 value = 18k\n",
      "R1 value = 1452k\n",
      "Divider leakage = 1.85 uA\n",
      "Sensing resistor = 10.0 mR\n",
      "Sensing resistor power dissipation = 0.64 W\n",
      "Worst case current = 9.0 A\n",
      "OC timer charge = 0.06 ms\n",
      "MOSFET power dissipation = 33.3 W\n",
      "Time to OC protection trip = 0.17 ms\n",
      "Timer capacitor C_T value = 45.32 nF\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "source": [
    "#BQ25798\n",
    "\n",
    "## Termistor settings\n",
    "# JEITA profile temperature points\n",
    "temp_T1 = 0     # °C\n",
    "temp_T5 = 60\n",
    "\n",
    "# NTC resistance at temperature points\n",
    "termistor_at_T1 = 29250.0\n",
    "termistor_at_T5 = 2900.0\n",
    "\n",
    "# Voltage of temperature level in fraction of REGN voltage\n",
    "temp_T1_threshold = 0.733\n",
    "temp_T5_threshold = 0.342\n",
    "\n",
    "resistor_RT2 = (termistor_at_T1*termistor_at_T5 * ((1.0/temp_T5_threshold)-(1.0/temp_T1_threshold))) / ((termistor_at_T1 * ((1.0/temp_T1_threshold) - 1))-(termistor_at_T5 * ((1.0/temp_T5_threshold) - 1)))\n",
    "resistor_RT1 = ((1.0/temp_T1_threshold) - 1) / ( (1.0 / resistor_RT2) + (1.0/termistor_at_T1) )\n",
    "\n",
    "print(\"Battery termistor resistor network\")\n",
    "print(\"RT1 = {} k\".format(round(resistor_RT1/1000,2)))\n",
    "print(\"RT2 = {} k\".format(round(resistor_RT2/1000,2)))\n",
    "\n",
    "## Input current limitation\n",
    "maximal_input_current_draw = 0.9 # in Amp\n",
    "divider_R1 = 100 # in kOhms\n",
    "\n",
    "voltage_REGN = 4.8\n",
    "\n",
    "voltage_ILIM = 1 + 0.8 * maximal_input_current_draw\n",
    "divider_R2 = round((voltage_ILIM * divider_R1) / (voltage_REGN - voltage_ILIM),3)\n",
    "print(\"ILIM voltage divider: R1 = {} kΩ, R2 = {} kΩ\".format(divider_R1,divider_R2))\n",
    "\n",
    "\n"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Battery termistor resistor network\n",
      "RT1 = 5.02 k\n",
      "RT2 = 26.07 k\n",
      "ILIM voltage divider: R1 = 100 kΩ, R2 = 55.844 kΩ\n"
     ]
    }
   ],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "source": [
    "# TPS6300\n",
    "\n",
    "output_voltages = [1.8,3.3,5.0]\n",
    "resistor_R2 = 200 # in kOhms, recommended 100-500 kR\n",
    "\n",
    "feedback_voltage = 0.5 # V\n",
    "\n",
    "for output_voltage in output_voltages:\n",
    "    resistor_R1 = resistor_R2 * (output_voltage/feedback_voltage-1)\n",
    "    print(\"Resistor R2 for output voltage {} V is: {} kΩ\".format(output_voltage, resistor_R1))\n"
   ],
   "outputs": [
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "Resistor R2 for output voltage 1.8 V is: 520.0 kΩ\n",
      "Resistor R2 for output voltage 3.3 V is: 1120.0 kΩ\n",
      "Resistor R2 for output voltage 5.0 V is: 1800.0 kΩ\n"
     ]
    }
   ],
   "metadata": {}
  }
 ]
}