Cheap simple UPS/Battery supply for projects.

If doesn't fit into any other category ....
Post Reply
peridot
Posts: 46
Joined: Mon Mar 08, 2021 4:54 am
Has thanked: 7 times
Been thanked: 93 times

Cheap simple UPS/Battery supply for projects.

Post by peridot »

Nice and simple UPS/Battery 18650 Li-on power supply which are easily hack-able if you want to make it a little smarter. These units , I got mine here

These units are cheap and perfect for using reclaimed 18650 cells from battery packs. Shown here is one of the new units and then a modified one adding a voltage adjustable/trimmed output and a mosfet controlled switched output. The supply could then run a small micro or raspberry Pi.

IMG_20230916_172058098 (Small).jpg
IMG_20230916_172114491 (Small).jpg
IMG_20230915_110844982 (Small).jpg

in these photos is the original prototype shown where a Picomite is controlling the PSU which then powers a Raspberry Pi Zero with soft power up/power down, UPS functions , power fail detection , Pi shutdown etc.

IMG_20230915_143755027 (Small).jpg
IMG_20230911_103630965 (Small).jpg
IMG_20230916_175103508.jpg
You do not have the required permissions to view the files attached to this post.
User avatar
cicciocb
Site Admin
Posts: 2092
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 448 times
Been thanked: 1385 times
Contact:

Re: Cheap simple UPS/Battery supply for projects.

Post by cicciocb »

Hi,
thanks for the tips and for your interesting solution.

I've bought some of them .... :D
peridot
Posts: 46
Joined: Mon Mar 08, 2021 4:54 am
Has thanked: 7 times
Been thanked: 93 times

Re: Cheap simple UPS/Battery supply for projects.

Post by peridot »

[Local Link Removed for Guests] wrote: [Local Link Removed for Guests]Mon Sep 18, 2023 2:26 pm Hi,
thanks for the tips and for your interesting solution.

I've bought some of them .... :D
Thanks for the support cicciob, code to drive the UPS is on the way.
peridot
Posts: 46
Joined: Mon Mar 08, 2021 4:54 am
Has thanked: 7 times
Been thanked: 93 times

Re: Cheap simple UPS/Battery supply for projects.

Post by peridot »

Here is a software package for ESP32 to go with the UPS/Battery pack. In this setup the UPS/Battery pack is working as a power supply for the ESP32 which may continue working when (mains) power fails. The ESP32 is always being powered by the UPS (mains or battery) but although not actually being used in this setup there is also a 5VDC switched output which can power other attached equipment.

Functions are :
Soft switch Running/standby controlling a switched 5VDC
Power fail detected
Time on UPS monitored , at expiration switched 5VDC is turned off, goes into standby
Power Restoration detected
On power restoration Startup occurs , switched 5VDC turned on.
Last known status retained if complete power removed from esp32

Code: [Local Link Removed for Guests]

  
  '  ' ***** Annex UPS *****
  ' *******************************
  '    Filename: ups.bas
  '    Date: Sept 2023
  '    File Version:
  '     Written by: M.Ogden
  '    Function: ups controller
  '   Device: esp32
  '    Last Revision:
  '    Initial v.5 ported from picomite (rpi-pico)
  '
  ' *******************************
  'Constants & Variables
  ver$="v0.5"
  flogs$="/root/logs/"
  fvar$="/root/cfg/var.dat"  'variables save address
  vvar$="" 'variables save contents
  no_battchg=0  'set if no battery charge pin
  max_task=15 'max number of tasks
  upsexpired=3600  'time in seconds allowed on battery (default 1Hr)
  cm$=",":q$=chr$(34):J$="&":temp1$="":temp$="":lastline$="":newline$=""
  'prop temp control, when used
  ffan=70
  fan_cycle=60
  temp_run=40
  stall_percent=30
  temp_max=55
  fan_ratio=((99-stall_percent)/(temp_max-temp_run))
  rt=0:it=0
  secs=0:flag=0 'periods
  uptime=0  'time up in seconds
  upspower=0  'ups power on
  upstime=0 'time on battery
  errflag=0 'error
  userprocessflag=0
  cdclock=20 ' seconds
  rpitemp$="45"
  rpiload$=""
  rpidate$="":rpitime$="":rpiutc$=""
  standby=0
  powerflag=0:powerfail=0
  powermsgflag=1
  dim tt(max_task)  'Task Timer array
  tx=0:ty=0
  '
  '***** User Variables ******
  
  
  
  ''ESP32 38pin dev kit Pin Numbers
  pipwr=27
  battchg=14
  upspwr=12
  pled=26
  nled=25
  aled=33
  butt=32
  fdrv=13 'when used
  ftemp=2 'when used
  
  'pin.mode IO
  pin.mode pled, output 'Power Led
  pin.mode nled, output 'Network Led
  pin.mode aled, output 'Activity Led
  pin.mode pipwr, output 'ups switched
  pin.mode butt,input ,pullup 'button
  interrupt butt, buttonpress  ' set button interrupt
  pin.mode battchg,input ,pullup 'ups battery charged input
  'interrupt battchg, battcharged  ' set ups battery charged interrupt
  pin.mode upspwr,input,pulldown 'ups power input
  interrupt upspwr, nopower' set ups power interrupt
  pin(pled)=0 'Power Led (on)
  pin(nled)=1 'Network Led (Off)
  pin(aled)=1 'Activity Led (Off)
  '
  ' Timers & Interupts
  'Task "Tick"  Timer List
  'tt(0)=Expired, tt(-1)=Disabled
  'setup initial tasks
  task 0,-1 ' usually run once on startup
  timer0 1000 ,T1   'establish seconds "Tick Timer"
  '
  'setup and Initialise
  ONERROR GOTO Error_Handler
  udp.begin 5001  'set the UDP commmunication using port 5001
  ONERROR GOTO Error_Handler
  option.WDT 20000    ' set the WDT at 10 second
  
  '********* Start Up *********
  wlog ""
  wlog"UPS - ";
  wlog"ver: "+ver$
  '
  varRestore
  if standby=1 then
  onudp off  'UDP receive Off
    wlog"Standby"
    led3 pled, 1 'power led off
    pin(pipwr)=1  'shutdown power supply
    ''pwm 1,ffan,stop  'off
  else
    'start up via Power Source check
    if pin(upspwr)=1 then
      powerflag=1
      gosub startupseq
    end if
  end if
  if no_battchg=1 then gosub battcharged 'get battery status
  
  '********* Main Loop *********
  'main loop processing
  'main:
  do
    it=millis
    option.WDTreset
    if standby =0 then
      
      task 0,-1
      'wlog"Run Tasks"
      task 2,10  'active
      
      
      '********************************************
      ' insert your main code here....
      '********************************************
    end if
    if upstime>upsexpired then shutdownseq
    'if upstime>some-triggerpoint then some-event
    'eg close down some other server
    rt=(millis-it)/1000
    ' wlog"Elapsed:";timer-looptime/1000
  loop
  '***** End main program loop
end
  
  
  
  
  
  'core routines
sub runonce
  settick 0,0,2 'disable timer
end sub
  
battcharged:
  if pin(battchg)=1 then return
  if pin(battchg)=0 then
    wlog"Battery is charged"
    upstime=0  'reset UPS timer
  else
    if pin(upspwr)=1 then
      wlog"Power On - Battery is charging"
    else
      wlog"Power Off - Battery not charged"
    end if
  end if
return
  
  'power plug interupt
nopower:
  pause 100  'debounce
  if no_battchg=1 then upstime=0  'reset UPS timer
  if pin(upspwr)=1 then
    wlog"Power OK"
    powerflag=1
    powermsgflag=1
    if powerfail=1 then gosub startupseq  'only start if in standby
  else
    if  powerfail=0 then
      wlog"Power Disconnected"
      wlog"UPS Power"
      textmsg "text","Power has been disconnected"
      if standby =0 then
        powerfail=1
        powerflag=0
        upstime=0 'reset time
      end if
    end if
  end if
return
  
  'sub notrunning
  'if standby=1 then exit sub
  'wlog"Pi Not-running"
  'shutdownseq
  'end sub
  
  'Heartbeat
T1:'Tick Timer
  'wlog"Standby:Cdclock";standby;" ";cdclock
  for tx= 0 to 15
    ty=tt(tx)
    if ty>0 then
      ty=ty-1
      tt(tx)=ty
    end if
  next tx
  if standby=0  then  'normal running
    uptime=uptime+1 'time while running
    if uptime=60 and powermsgflag=0 then powermsgflag=1 'set flag 60secs after power restored
  else      'in standby
    task 1,5
  end if
  if powerflag=0 then
    upstime=upstime+1 'time in disconnected and on ups power
    task 1,5 'in No Power
  end if
  if errflag=1 then
    led2 pled
  end if
  'wlog"Uptime:";uptime;" upstime:";upstime
return
  
  'task run , t- task#, l- load value
sub task(tsk,lsk)
  'wlog"Task";str$(tsk)
  if tsk>max_task then exit sub
  if tt(tsk)<0 then exit sub
  if tt(tsk)>0 then exit sub
  tt(tsk)=lsk
  select case tsk
    case 0
      gosub onstartup
    case 1  '5 secs
      LED1 pled ,100
      if powerflag=0 then gosub upsruntime  'print UPS running time
    case 2  '10 secs
      'adjFanSpeed val(rpitemp$)
      'textmsg "cpucore",str$(val(rpitemp$),2,1)
    case 3
      'blank
    case 4
      'midnight
    case 9
      'wlog"********************************** HTTP, UDP data"
    case 5
      '
    case 6
      '
    case 7
      status
    case 8
      '
    case 9
      '
    case 10
      '
    case 11
      '
    case else
      tt(tsk)=-1 'stop the task
      'wlog"No Task! - stop the task"
      
  end select
end sub
  
  'Led1 pulse p=pin
sub led1(le,d)
  if d=0 then d=50
  if pin(le)=1 then
    pin(le)=0
    pause d
    pin(le)=1
  else
    pin(le)=1
    pause d
    pin(le)=0
  end if
end sub
  
  'Led2 toggle
sub led2(le)
  if pin(le)=1 then
    pin(le)=0
  else
    pin(le)=1
  end if
end sub
  
  'Led3 set
sub led3(le,hl)
  pin(le)=hl
end sub
  
upsruntime:
  wlog "UPS RunTime"
  wlog uptime;"  ";upstime
  textmsg "text","Will close down in "+str$(upsexpired-upstime/60,"%6.0f")+" mins"
  wlog"Will close down in ";str$(upsexpired-upstime/60,"%6.0f")+" mins"
 return
  
  
  # Set the 'pwm of fan pin
sub adjFanSpeed(CPU_temp)
  if  CPU_temp > temp_run then
    FAN_cycle = (((CPU_temp - temp_run)*fan_ratio)+stall_percent)
    FAN_cycle = min(100,max(stall_percent,FAN_cycle))
    'pwm 1,ffan,fan_cycle
  else
    'pwm 1,ffan,stop  'off
    FAN_cycle=0
  end if
end sub
  
  
sub textmsg(obj$,tmsg$)
  'print#5, "{"+q$+obj$+q$+":"+q$+tmsg$+q$+"}"
end sub
  
  
buttonpress:
  if pin(butt)=1 then return
  wlog "button"
  pause 50  'debounce
  if pin(butt)=0 then gosub presstime
return
  
presstime:
  wlog "button presstime"
  pause 1000
  if pin(butt)=0 then
    if standby=0 then   'running
      gosub shutdownseq
    else
      'start up via Power Source check
      wlog"Check Power:";pin(upspwr)
      if pin(upspwr)=1 then
        powerflag=1
        gosub startupseq
      end if
    end if
  else
    wlog"shortpress"
    led1 pled,100
  end if
return
  
shutdownseq:
  option.WDTreset ' reset
  onudp off  'UDP receive off
  wlog"Shutdown"
  textmsg "text","Shutting down RPI"
  led1 pled, 1000
  'pin(pishdn)=0  'shutdown RPI
  'pause 1000
  'pin(pishdn)=1
  wlog"Standby"
  errflag=0
  standby=1
  OPTION.CPUFREQ 80
  wlog"RPI-Shutdown Delay"
  pause 15000' Wait for pi to shutdown
  led3 pled, 1 'power led off
  wifi.sleep
  wlog"shutdown supply"
  pin(pipwr)=1  'shutdown RPI power supply
  'pwm 1,ffan,stop  'off
  varSave
return
  
startupseq:
  wlog"Startup"
  led1 pled,1000
  uptime=0
  pin(pipwr)=0  'power supply on
  uptime=0
  upstime=0
  standby=0
  powerfail=0
  OPTION.CPUFREQ 240
  varSave
  wifi.awake
  pause 2000
  onudp gudp  'UDP receive
  led3 pled, 0  'power led on
  'pwm 1,ffan,60 'Run fan default
  wlog"Running"
return
  
  
gudp:
  v$ = udp.read$
  pause 100
  'wlog "UDP:";v$
  led1 nled,100
  newline$=v$
  v$=""
  return
  
  
sub varRestore
  if file.exists(fvar$) then
    vvar$=file.read$(fvar$)
    standby=val(word$(vvar$,1))
    powerfail=val(word$(vvar$,2))
  end if
end sub
  
sub varSave
  FILE.SAVE fvar$, str$(standby)+cm$+str$(powerfail)
end sub
  
sub onStartup
  wlog"On-Startup"
end sub
  
Error_Handler:
  temp$=flogs$+"err.txt"
  temp1$="Error text:"+BAS.ErrMsg$+" ,Error num="+str$(BAS.ErrNum)+" ,Error line="+str$(BAS.ErrLine)
  wlog temp1$
  msglog temp$,temp1$
Return ' returns to the line following the error
  
sub msglog(f$,msg$)
  file.append f$,date$+","+time$+","+msg$+chr$(13)+chr$(10)
end sub
  
onStartup:
  temp$=flogs$+"logs.txt"
  select case BAS.RESETREASON
      case 0: msglog temp$,"Unknown"
      case 1: msglog temp$, "Power on reset"
      case 2: msglog temp$, "Unknown"
      case 3: msglog temp$, "Software reset digital core"
      case 4: msglog temp$, "Legacy watch dog reset digital c"
      case 5: msglog temp$, "Deep Sleep reset digital core"
      case 6: msglog temp$, "Reset by SLC module, reset digital core"
      case 7: msglog temp$, "Timer Group0 Watch dog reset digital core"
      case 8: msglog temp$, "Timer Group1 Watch dog reset digital core"
      case 9: msglog temp$, "RTC Watch dog reset digital core"
      case 10: msglog temp$, "Intrusion tested to reset CPU"
      case 11: msglog temp$, "Time Group reset CPU"
      case 12: msglog temp$, "Software reset CPU"
      case 13: msglog temp$, "RTC Watch dog reset CPU"
      case 14: msglog temp$, "for APP CPU, reset by PRO CPU"
      case 15: msglog temp$, "Reset when the vdd voltage is not stable"
      case 16: msglog temp$, "RTC Watch dog reset digital core and rtc module"
    case else
      msglog temp$, "Code-"+str$(BAS.RESETREASON)
  end select
return
  
  '**************** End Core routines and functions ********
  
  
  
  'user subs and tasks
  '*** User subs and other code here ***
  
  
  'End user subs and tasks
  
User avatar
cicciocb
Site Admin
Posts: 2092
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 448 times
Been thanked: 1385 times
Contact:

Re: Cheap simple UPS/Battery supply for projects.

Post by cicciocb »

Thanks for your code, I'll try it in a near future ....
Post Reply