Programmable LED bar

Place your projects here
Post Reply
User avatar
Fernando Perez
Posts: 378
Joined: Mon Feb 15, 2021 10:09 pm
Location: Santander (Spain)
Has thanked: 195 times
Been thanked: 267 times

Programmable LED bar

Post by Fernando Perez »

Really, this new device that I have created only serves to help elderly and pregnant women perform Kegel exercises.
Since I do not believe that these circumstances arise among you, :roll: it will be of no more use than to note that I am increasingly programming in a more cryptic and concise way.
However, if any of the routines it contains or the way the program is designed helps you develop your ideas, I will be happy.
It is an ESP8266 module mounted on a double Wemos base, with its corresponding battery shield, and a homemade shield with a 10-LED bar.

https://youtu.be/DdSL-3nP-KQ

To save battery, I disconnect the Wifi by checking the "Fast boot" box on the configuration page and putting it as the first instruction to execute in the wifi.sleep program.
But for when the user wants to change the times or we want to edit the programs, there is a second program that runs wifi.connect "router", "password" and allows access.
Whether one program or another is loaded when the module is turned on depends on how we power it, whether by battery or by a USB cable.
And to distinguish the power mode, I measure in a third program (actually program zero) the voltage on the ADC pin.
If it is less than 100, powered by USB and load program with Wifi.
If it is larger, battery power and load the main program.

FILE: /kegel.bas

Code: [Local Link Removed for Guests]

' Check whether it is connected to the battery or USB
' and load the corresponding program.
wifi.sleep
if ADC < 100 then
  r = bas.load "/conWifi.bas"
else
  r = bas.load "/sinWifi.bas"
endif 

FILE: /sinwifi.bas

Code: [Local Link Removed for Guests]

' Battery has been detected, activate KEGEL.
wifi.sleep
port &B11111111111 ' All GPIOs will be OUTPUT

file$ = "/kegel.dat" : dat$ = ""
if file.exists(file$) = 0 then gosub createConfig else gosub readConfig
  
for times = 1 to repeat

  for n = 9 to 0 step -1
    pinout 1024 - (2^n)
    pin.tone 16, 500, 200
    pause rising*100
  next n

  for n = 1 to 10
    pinout 1024 - (2^n)
    pin.tone 16, 1000, 200
    pause rising*100
  next n
 
next times

END

' -----------
createConfig:
  word.setParam dat$, "rising", "10"
  word.setParam dat$, "faling", "10"
  word.setParam dat$, "repeat", "10"
  file.append file$, dat$
return
' ---------
readConfig:
  dat$ = file.read$(file$)
  rising = val(word.getParam$(dat$, "rising"))
  faling = val(word.getParam$(dat$, "faling"))
  repeat = val(word.getParam$(dat$, "repeat"))
return   

' === SUBROUTINES ======== 
' --------------
SUB port(config)
LOCAL gpio
  config =((config\64)*4032) + config  ' Insert zeros for GPIO 6 to 11
  for gpio = 0 to 16
    if (gpio<6) OR (gpio>11) then  ' skipping GPIO reserved
      if (config and (1 << gpio)) <> 0 then pin.mode gpio,output else pin.mode gpio,input ' [,pullup]
    endif
  next gpio 
END SUB
' ----------------
SUB pinout(adress)
LOCAL ofset
  ofset = (adress\64) * 4032
  BAS.POKE &H60000300, adress + ofset
END SUB

FILE: /conwifi.bas

Code: [Local Link Removed for Guests]

' No battery detected, activate Wifi.
wifi.connect "MYWIFI_Name", "xXxXxXxX" 
port &B11111111111 ' All GPIOs will be OUTPUT
swing 4, 50  ' The LED bar oscillates to indicate that we are in Wifi mode

file$ = "/kegel.dat" : dat$ = ""
if file.exists(file$) = 0 then gosub createConfig else gosub readConfig

onHtmlReload web
gosub web
wait

END

' --
web:
  cls
  cssExternal "/main.css"
  a$ = "<center>"
  a$ = a$ + |<h1>RISING TIME</h1>|
  a$ = a$ + button$("-R", updated, "btn1") + textBox$(rising, "txt1") + button$("+R", updated, "btn1")
  a$ = a$ + |<h1>FALING TIME</h1>|
  a$ = a$ + button$("-F", updated, "btn1") + textBox$(faling, "txt1") + button$("+F", updated, "btn1")
  a$ = a$ + |<h1>TIMES REPEAT</h1>|
  a$ = a$ + button$("-T", updated, "btn1") + textBox$(repeat, "txt1") + button$("+T", updated, "btn1")
  a$ = a$ + button$("Save", updated, "button")   
  html a$
return
' ------
updated:
  btn$ = htmlEventButton$
  SELECT CASE btn$
    CASE "-R" : rising = rising - 1
    CASE "+R" : rising = rising + 1
    CASE "-F" : faling = faling - 1
    CASE "+F" : faling = faling + 1
    CASE "-T" : repeat = repeat - 1
    CASE "+T" : repeat = repeat + 1
    CASE "Save"
      gosub updateConfig
      jscall |{alert("The new values have been saved.");}|
  END SELECT      
  refresh
return
' -----------
createConfig:
  word.setParam dat$, "rising", "10"
  word.setParam dat$, "faling", "10"
  word.setParam dat$, "repeat", "10"
  file.append file$, dat$
return
' -----------
updateConfig:
  word.setParam dat$, "rising", str$(rising)
  word.setParam dat$, "faling", str$(faling)
  word.setParam dat$, "repeat", str$(repeat)
  file.save file$, dat$
return
' ---------
readConfig:
  dat$ = file.read$(file$)
  rising = val(word.getParam$(dat$, "rising"))
  faling = val(word.getParam$(dat$, "faling"))
  repeat = val(word.getParam$(dat$, "repeat"))
return   

' === SUBROUTINES ======== 
' --------------
SUB port(config)
LOCAL gpio
  config =((config\64)*4032) + config  ' Insert zeros for GPIO 6 to 11
  for gpio = 0 to 16
    if (gpio<6) OR (gpio>11) then  ' skipping GPIO reserved
      if (config and (1 << gpio)) <> 0 then pin.mode gpio,output else pin.mode gpio,input ' [,pullup]
    endif
  next gpio 
END SUB
' ----------------
SUB pinout(adress)
LOCAL ofset
  ofset = (adress\64) * 4032
  BAS.POKE &H60000300, adress + ofset
END SUB
' ---------------------
SUB swing(times, speed)
LOCAL n, i
  dim patern(5) = 0, 513, 771, 903, 975, 1023
  for n = 1 to times
    for i = 0 to 5
      pinout patern(i)
      pause speed
    next i
    for i = 5 to 0 step -1
      pinout patern(i)
      pause speed
    next i
  next n
END SUB

FILE: /main.css

Code: [Local Link Removed for Guests]

h1 {
  font-family: "trebuchet ms";
  font-size: 1.7rem;
  margin: 10px;
}

#txt1 {
  font-family: verdana;
  font-size: 1.5rem;
  font-weight: 600;
  text-align: center;
  height: 50px;
  width: 6rem;
 /*  background: #FFE4C4; */
  background: #D0E4C4;
}

#btn1 {
  font-family: verdana;
  font-size: 1.5rem;
  font-weight: 600;
  text-align: center;
  color: #14396A !important;
  height: 50px;
  width: 5rem;
  background: #63B8EE;
}

#button {
  display: block;
  width: 150px;
  margin: 40px 10px 20px 25px;
  padding: 10px 20px;
  border: none;
  border-radius: 16px;
  color: black;
  background-color: #ddd;
  text-align: center;
  font-size: 1.2rem;
  font-weight: 600; 
  cursor: pointer;
  box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
}

Don't forget, on the Configuration page, to fill in the Autorun file with the name of your zero file.
In my case, /kegel.bas.
You do not have the required permissions to view the files attached to this post.
Last edited by Fernando Perez on Mon Dec 11, 2023 5:30 pm, edited 2 times in total.
User avatar
PeterN
Posts: 391
Joined: Mon Feb 08, 2021 7:56 pm
Location: Krefeld, Germany
Has thanked: 184 times
Been thanked: 219 times
Contact:

Re: Programmable LED bar

Post by PeterN »

My small prosperity belly only gently hints at pregnancy ;-)
My respect goes not only to the clean positioning of the SMD resistors on the perfboard but also to the programming!
Post Reply