Page 14 of 17

Re: GPIO.input voltage levels vs edge detection

Posted: Fri Nov 02, 2018 9:37 am
by tlfong01
tlfong01 wrote:
Fri Nov 02, 2018 6:01 am
Problem: Cannot blink two LEDs at the same time

Testing one shot timers OK

I still have not found why I cannot blink two LEDs at the same time. But I found it possible to blink one LED using not stop timer and at the same time set another LED high or low, using one shot timer.

I think using non stop timer (ALARM_AUTO) is error prone, because the timer hides in the background and often causes trouble. It is safe to use one shot timer (ALARM_SINGLE). I have tested one shot timer OK. Next step is to try to simulate blocking busy looping using one or two one shot timers.

function main()
printTitle('blinky2018nov0203a')

-- *** Blink D4 non stop using Timer1 (stop Timer2) ***
---[[
pinNum = D4; timerNum = 1; toggleTime = FiveHundredMilliSeconds
stopTimer(Timer2)
togglePin04(pinNum, timerNum, toggleTime)

--]]

-- *** Blink D0 non stop using Timer2 (stop Timer 1) ***
--[[
pinNum = D0; timerNum = 2; toggleTime = OneHundredMilliSeconds
stopTimer(Timer1)
togglePin04(pinNum, timerNum, toggleTime)

--]]

-- *** Hold D4 High***
--[[
stopTimer(Timer1)
pinNum = D4; timerNum = Timer1; highTime = TwoSeconds
holdPinHigh05(pinNum, timerNum, highTime)

--]]

-- *** Hold D4 Low***

--[[
stopTimer(Timer1)
pinNum = D4; timerNum = Timer1; lowTime = FourSeconds
holdPinLow05(pinNum, timerNum, lowTime)

--]]

end


Code: Select all

-- *** Blinky2018nov0203a tlfong01 2018nov02hkt1718 *** --

-- *** Globla Variables *** --------------------------------------------------

High   = true
Low    = false

Output = true
Input  = false

Timer1 = 1
Timer2 = 2

D4     = 4
D0     = 0

OneHundredMilliSeconds   = 100
FiveHundredMilliSeconds  = 500
OneSecond                = 1000
TwoSeconds               = 2000
FourSeconds              = 4000

-- *** Debug Print Functions *** ---------------------------------------------

function printTitle(title)
  local threeStars = '***'
  local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'
  local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- *** GPIO Functions *** ----------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

function invertPinLevel(PinLevel)
  if pinLevel == High
    then
      pinLevel = Low
    else
      pinLevel = High
  end
end

-- *** Timer Functions *** ---------------------------------------------------

function stopTimer(timerNum)
  tmr.stop(timerNum)
end

-- *** togglePin04 Blink LED Non Stop *** -------------------------------------------------------

function togglePin04(pinNum, timerNum, toggleTime)
  setPinMode(pinNum, Output)
  pinLevel = High

  function togglePin04CallBack()
    invertPinLevel(pinLevel)
    setPinLevel(pinNum, pinLevel)
  end

  tmr.alarm(timerNum, toggleTime, tmr.ALARM_AUTO, togglePin04CallBack)
end

-- *** holdPinHigh/Low05 *** -------------------------------------------------

function holdPinHigh05(pinNum, timerNum, highTime)
  setPinMode(pinNum, Output)
  setPinHigh(pinNum)  

  function holdPinHigh05CallBack()
    setPinLow(pinNum)
  end

  tmr.alarm(timerNum, highTime, tmr.ALARM_SINGLE, holdPinHigh05CallBack)
end

function holdPinLow05(pinNum, timerNum, lowTime)
  setPinMode(pinNum, Output)
  setPinLow(pinNum)  

  function holdPinLow05CallBack()
    setPinHigh(pinNum)
  end

  tmr.alarm(timerNum, lowTime, tmr.ALARM_SINGLE, holdPinLow05CallBack)
end


-- *** Main Function *** -----------------------------------------------------

function main()
  printTitle('blinky2018nov0203a')

  -- *** Blink D4 non stop using Timer1 (stop Timer2) ***
  ---[[
  pinNum = D4; timerNum = 1; toggleTime = FiveHundredMilliSeconds
  stopTimer(Timer2)
  togglePin04(pinNum, timerNum, toggleTime)
  --]]

  -- *** Blink D0 non stop using Timer2 (stop Timer 1) ***
  --[[
  pinNum = D0; timerNum = 2; toggleTime = OneHundredMilliSeconds
  stopTimer(Timer1)
  togglePin04(pinNum, timerNum, toggleTime)
  --]]

  -- *** Hold D4 High***
  --[[
  stopTimer(Timer1)
  pinNum = D4; timerNum = Timer1; highTime = TwoSeconds
  holdPinHigh05(pinNum, timerNum, highTime)
  --]]

  -- *** Hold D4 Low***
  --[[
  stopTimer(Timer1)
  pinNum = D4; timerNum = Timer1; lowTime = FourSeconds
  holdPinLow05(pinNum, timerNum, lowTime)
  --]]

end  

-- *** Main *** --------------------------------------------------------------

main()

-- *** End *** ---------------------------------------------------------------

Re: GPIO.input voltage levels vs edge detection

Posted: Fri Nov 02, 2018 1:35 pm
by tlfong01
tlfong01 wrote:
Fri Nov 02, 2018 9:37 am
tlfong01 wrote:
Fri Nov 02, 2018 6:01 am
Problem: Cannot blink two LEDs at the same time
Testing one shot timers OK
I think using non stop timer (ALARM_AUTO) is error prone, because the timer hides in the background and often causes trouble. It is safe to use one shot timer (ALARM_SINGLE). I have tested one shot timer OK. Next step is to try to simulate blocking busy looping using one or two one shot timers.

My first NodeMCU Lua Blinky program, no blocking busy looping, all event driven, finally completed, taking the newbie two weeks! :lol:

I found that one shot timer using ALARM_SINGLE kills itself on expiry, therefore not useful to do continuous blinking. Instead I should use ALARM_SEMI timers, which sleep on expiry, and can manually resume.

Now I can now start a continuously blinking LED using the following two statements:

pinNum = D4; highTime = HalfSecond; lowTime = OneSecond;
togglePin06(pinNum, highTime, lowTime)

Code: Select all

-- *** Blinky2018nov0204a tlfong01 2018nov02hkt2109 *** --

-- *** Globla Variables *** --------------------------------------------------

High   = true
Low    = false

Output = true
Input  = false

Timer1 = 1
Timer2 = 2

D4     = 4
D0     = 0

OneHundredMilliSeconds   = 100
FiveHundredMilliSeconds  = 500
HalfSecond               = 500
OneSecond                = 1000
TwoSeconds               = 2000
FourSeconds              = 4000

-- *** Debug Print Functions *** ---------------------------------------------

function printTitle(title)
  local threeStars = '***'
  local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'
  local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- *** GPIO Functions *** ----------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

function invertPinLevel(PinLevel)
  if pinLevel == High
    then
      pinLevel = Low
    else
      pinLevel = High
  end
end

-- *** Timer Functions *** ---------------------------------------------------

function stopTimer(timerNum)
  tmr.stop(timerNum)
end

-- *** togglePin04 Blink LED Non Stop *** -------------------------------------------------------

function togglePin04(pinNum, timerNum, toggleTime)
  setPinMode(pinNum, Output)
  pinLevel = High

  function togglePin04Callback()
    invertPinLevel(pinLevel)
    setPinLevel(pinNum, pinLevel)
  end

  tmr.alarm(timerNum, toggleTime, tmr.ALARM_AUTO, togglePin04Callback)
end

-- *** holdPinHigh/Low05 *** -------------------------------------------------

function holdPinHigh05(pinNum, timerNum, highTime)
  setPinMode(pinNum, Output)
  setPinHigh(pinNum)  

  function holdPinHigh05Callback()
    setPinLow(pinNum)
  end

  tmr.alarm(timerNum, highTime, tmr.ALARM_SINGLE, holdPinHigh05Callback)
end

function holdPinLow05(pinNum, timerNum, lowTime)
  setPinMode(pinNum, Output)
  setPinLow(pinNum)  

  function holdPinLow05Callback()
    setPinHigh(pinNum)
  end

  tmr.alarm(timerNum, lowTime, tmr.ALARM_SINGLE, holdPinLow05Callback)
end

-- *** togglePin06 *** -------------------------------------------------------

function togglePin06(pinNum, highTime, lowTime)

  -- Debug Print Statements ***
  printTitle('Begin togglePin06, ...')

  -- Callback Functions ***
  function highTimer06Callback()
    setPinLow(pinNum) 
    lowTimer:start()
  end

  function lowTimer06Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  highTimer = tmr.create()
  lowTimer  = tmr.create()

  -- *** Config Timers ***

  highTimer:register(highTime, tmr.ALARM_SEMI, highTimer06Callback)
  lowTimer:register (lowTime,  tmr.ALARM_SEMI, lowTimer06Callback)

  -- *** Init Pin and Start highTimer***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  highTimer:start()
  
end

-- *** Main Function *** -----------------------------------------------------

function main()
  printTitle('Begin blinky2018nov0204a(),... ')

  -- *** Toggle D4 pin non stop using Timer1 (stop Timer2) ***
  --[[
  pinNum = D4; timerNum = 1; toggleTime = FiveHundredMilliSeconds
  stopTimer(Timer2)
  togglePin04(pinNum, timerNum, toggleTime)
  --]]

  -- *** Toggle D0 pin non stop using Timer2 (stop Timer 1) ***
  --[[
  pinNum = D0; timerNum = 2; toggleTime = OneHundredMilliSeconds
  stopTimer(Timer1)
  togglePin04(pinNum, timerNum, toggleTime)
  --]]

  -- *** Set and Hold D4 pin High***
  --[[
  stopTimer(Timer2)
  pinNum = D4; timerNum = Timer1; highTime = TwoSeconds
  holdPinHigh05(pinNum, timerNum, highTime)
  --]]

  -- *** Set and Hold D4 pin Low***
  --[[
  stopTimer(Timer2)
  pinNum = D4; timerNum = Timer1; lowTime = FourSeconds
  holdPinLow05(pinNum, timerNum, lowTime)
  --]]

  -- *** Toggle D4 Pin ***
  ---[[
  stopTimer(Timer1)
  pinNum = D4; highTime = HalfSecond; lowTime = OneSecond;
  togglePin06(pinNum, highTime, lowTime)
  --]]

end  
-- *** Main *** --------------------------------------------------------------

main()

-- *** End *** ---------------------------------------------------------------

Re: GPIO.input voltage levels vs edge detection

Posted: Sat Nov 03, 2018 1:58 am
by tlfong01
tlfong01 wrote:
Fri Nov 02, 2018 1:35 pm
My first NodeMCU Lua Blinky program, no blocking busy looping, all event driven, finally completed, taking the newbie two weeks!

NodeMCU ESPlorer Snippet Writing Notes

Now that I know how to write a basic timer event driven blinky function, I think I should do two things.

1. Improve the blinky program to make it more newbie friendly, ie, making it easy to understand, easy to use, and easy to maintain and expand.

2. Find out how to use this basic blinky program as (a) init.lua, (b) as snippets. This is the first time I will upload and save init.lua, and second time playing with a snippet. So I will go very slowly.

I have executed the blinky program one more time, and logged everything, to see what actually is going on in the ESPlorer. The log is listed below.

I noticed the following error or warning message. I don't know why I have this problem. I need to look into it later.

Flash sig not correct: 0 vs fafaaf50

I also noticed that during booting, the IDE automatically loads the previously saved snippets in flash to RAM (I think). This means I should not be saving too many long snippets into flash, causing long load time during boot, and wasting RAM space unnecessarily.



Code: Select all


*** Results Window Output 2018nov03hkt0941***

PORT OPEN 115200
Communication with MCU..Got answer! Communication with MCU established.
AutoDetect firmware...
Can't autodetect firmware, because proper answer not received (may be unknown firmware). 
Please, reset module or continue.
...

Flash sig not correct: 0 vs fafaaf50
NodeMCU custom build by frightanic.com
  branch: master
  commit: c708828bbe853764b9de58fb8113a70f5a24002d
  SSL: false
  modules: dht,ds18b20,file,gpio,hdc1080,http,i2c,mqtt,net,node,ow,pcm,pwm,rtctime,spi,tmr,uart,wifi
  build created on 2018-10-25 07:35
  powered by Lua 5.1.4 on SDK 2.2.1(6ab97e9)
  lua: cannot open init.lua
> 

*** Log Window Output 2018nov03hkt0941 ***

Logging enable
Load saved settings: Firmware:NodeMCU
Snippets: loading...
Snippets load: Success.
Set new color theme: Success.
Load saved settings: DONE.
Snippets: loading...
Snippets load: Success.
Scan system...
found last saved serial port COM27
Scan done.
Serial port COM27 save as default.
Baud rate 115200 save as default.
Try to open port COM27, baud 115200, 8N1
Open port COM27 - Success.
Snippet name set to:Snippet0
Snippet name set to:Snippet1
Snippet name set to:Snippet0

*** Snippet 0 Listing ***

    l = file.list();
    for k,v in pairs(l) do
      print("name:"..k..", size:"..v)
    end

*** Blinky2018nov0204a Execution Record ***

> -- *** Blinky2018nov0204a tlfong01 2018nov02hkt2109 *** --
> 
> -- *** Globla Variables *** --------------------------------------------------
> 
> High   = true
> Low    = false
> 
> Output = true
> Input  = false
> 
> Timer1 = 1
> Timer2 = 2
> 
> D4     = 4
> D0     = 0
> 
> OneHundredMilliSeconds   = 100
> FiveHundredMilliSeconds  = 500
> HalfSecond               = 500
> OneSecond                = 1000
> TwoSeconds               = 2000
> FourSeconds              = 4000
> 
> -- *** Debug Print Functions *** ---------------------------------------------
> 
> function printTitle(title)
>> local threeStars = '***'
>> local twoNewLines = '\n\n'
>> print(twoNewLines, threeStars, title, threeStars)
>> end
> 
> function printTitleNum(title, num)
>> local twoNewLines = '\n\n'
>> local fiveSpaces = '     '
>> print(fiveSpaces, title, num)
>> end
> 
> -- *** GPIO Functions *** ----------------------------------------------------
> 
> function setPinMode(pinNum, pinMode)
>> if pinMode == Output
>> then
>> gpio.mode(pinNum, gpio.OUTPUT)
>> else
>> gpio.mode(pinNum, gpio.INPUT)
>> end
>> end
> 
> function setPinHigh(pinNum)
>> gpio.write(pinNum, gpio.HIGH)
>> end
> 
> function setPinLow(pinNum)
>> gpio.write(pinNum, gpio.LOW)
>> end
> 
> function setPinLevel(pinNum, pinLevel)
>> if pinLevel == High
>> then
>> setPinHigh(pinNum)
>> else
>> setPinLow(pinNum)
>> end
>> end
> 
> function invertPinLevel(PinLevel)
>> if pinLevel == High
>> then
>> pinLevel = Low
>> else
>> pinLevel = High
>> end
>> end
> 
> -- *** Timer Functions *** ---------------------------------------------------
> 
> function stopTimer(timerNum)
>> tmr.stop(timerNum)
>> end
> 
> -- *** togglePin04 Blink LED Non Stop *** -------------------------------------------------------
> 
> function togglePin04(pinNum, timerNum, toggleTime)
>> setPinMode(pinNum, Output)
>> pinLevel = High
>> 
>> function togglePin04Callback()
>> invertPinLevel(pinLevel)
>> setPinLevel(pinNum, pinLevel)
>> end
>> 
>> tmr.alarm(timerNum, toggleTime, tmr.ALARM_AUTO, togglePin04Callback)
>> end
> 
> -- *** holdPinHigh/Low05 *** -------------------------------------------------
> 
> function holdPinHigh05(pinNum, timerNum, highTime)
>> setPinMode(pinNum, Output)
>> setPinHigh(pinNum)
>> 
>> function holdPinHigh05Callback()
>> setPinLow(pinNum)
>> end
>> 
>> tmr.alarm(timerNum, highTime, tmr.ALARM_SINGLE, holdPinHigh05Callback)
>> end
> 
> function holdPinLow05(pinNum, timerNum, lowTime)
>> setPinMode(pinNum, Output)
>> setPinLow(pinNum)
>> 
>> function holdPinLow05Callback()
>> setPinHigh(pinNum)
>> end
>> 
>> tmr.alarm(timerNum, lowTime, tmr.ALARM_SINGLE, holdPinLow05Callback)
>> end
> 
> -- *** togglePin06 *** -------------------------------------------------------
> 
> function togglePin06(pinNum, highTime, lowTime)
>> 
>> -- Debug Print Statements ***
>> printTitle('Begin togglePin06, ...')
>> 
>> -- Callback Functions ***
>> function highTimer06Callback()
>> setPinLow(pinNum)
>> lowTimer:start()
>> end
>> 
>> function lowTimer06Callback()
>> setPinHigh(pinNum)
>> highTimer:start()
>> end
>> 
>> -- *** Create Timers ***
>> highTimer = tmr.create()
>> lowTimer  = tmr.create()
>> 
>> -- *** Config Timers ***
>> 
>> highTimer:register(highTime, tmr.ALARM_SEMI, highTimer06Callback)
>> lowTimer:register (lowTime,  tmr.ALARM_SEMI, lowTimer06Callback)
>> 
>> -- *** Init Pin and Start highTimer***
>> setPinMode(pinNum, Output)
>> setPinHigh(pinNum)
>> highTimer:start()
>> 
>> end
> 
> -- *** Main Function *** -----------------------------------------------------
> 
> function main()
>> printTitle('Begin blinky2018nov0204a(),... ')
>> 
>> -- *** Toggle D4 pin non stop using Timer1 (stop Timer2) ***
>> --[[
>> pinNum = D4; timerNum = 1; toggleTime = FiveHundredMilliSeconds
>> stopTimer(Timer2)
>> togglePin04(pinNum, timerNum, toggleTime)
>> --]]
>> 
>> -- *** Toggle D0 pin non stop using Timer2 (stop Timer 1) ***
>> --[[
>> pinNum = D0; timerNum = 2; toggleTime = OneHundredMilliSeconds
>> stopTimer(Timer1)
>> togglePin04(pinNum, timerNum, toggleTime)
>> --]]
>> 
>> -- *** Set and Hold D4 pin High***
>> --[[
>> stopTimer(Timer2)
>> pinNum = D4; timerNum = Timer1; highTime = TwoSeconds
>> holdPinHigh05(pinNum, timerNum, highTime)
>> --]]
>> 
>> -- *** Set and Hold D4 pin Low***
>> --[[
>> stopTimer(Timer2)
>> pinNum = D4; timerNum = Timer1; lowTime = FourSeconds
>> holdPinLow05(pinNum, timerNum, lowTime)
>> --]]
>> 
>> -- *** Toggle D4 Pin ***
>> ---[[
>> stopTimer(Timer1)
>> pinNum = D4; highTime = HalfSecond; lowTime = OneSecond;
>> togglePin06(pinNum, highTime, lowTime)
>> --]]
>> 
>> end
> -- *** Main *** --------------------------------------------------------------
> 
> main()


	***	Begin blinky2018nov0204a(),... 	***


	***	Begin togglePin06, ...	***
> 
> -- *** End *** ---------------------------------------------------------------
> 

*** Blinky2018nov0204a Program Listing ***

-- *** Blinky2018nov0204a tlfong01 2018nov02hkt2109 *** --

-- *** Globla Variables *** --------------------------------------------------

High   = true
Low    = false

Output = true
Input  = false

Timer1 = 1
Timer2 = 2

D4     = 4
D0     = 0

OneHundredMilliSeconds   = 100
FiveHundredMilliSeconds  = 500
HalfSecond               = 500
OneSecond                = 1000
TwoSeconds               = 2000
FourSeconds              = 4000

-- *** Debug Print Functions *** ---------------------------------------------

function printTitle(title)
  local threeStars = '***'
  local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'
  local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- *** GPIO Functions *** ----------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

function invertPinLevel(PinLevel)
  if pinLevel == High
    then
      pinLevel = Low
    else
      pinLevel = High
  end
end

-- *** Timer Functions *** ---------------------------------------------------

function stopTimer(timerNum)
  tmr.stop(timerNum)
end

-- *** togglePin04 Blink LED Non Stop *** -------------------------------------------------------

function togglePin04(pinNum, timerNum, toggleTime)
  setPinMode(pinNum, Output)
  pinLevel = High

  function togglePin04Callback()
    invertPinLevel(pinLevel)
    setPinLevel(pinNum, pinLevel)
  end

  tmr.alarm(timerNum, toggleTime, tmr.ALARM_AUTO, togglePin04Callback)
end

-- *** holdPinHigh/Low05 *** -------------------------------------------------

function holdPinHigh05(pinNum, timerNum, highTime)
  setPinMode(pinNum, Output)
  setPinHigh(pinNum)  

  function holdPinHigh05Callback()
    setPinLow(pinNum)
  end

  tmr.alarm(timerNum, highTime, tmr.ALARM_SINGLE, holdPinHigh05Callback)
end

function holdPinLow05(pinNum, timerNum, lowTime)
  setPinMode(pinNum, Output)
  setPinLow(pinNum)  

  function holdPinLow05Callback()
    setPinHigh(pinNum)
  end

  tmr.alarm(timerNum, lowTime, tmr.ALARM_SINGLE, holdPinLow05Callback)
end

-- *** togglePin06 *** -------------------------------------------------------

function togglePin06(pinNum, highTime, lowTime)

  -- Debug Print Statements ***
  printTitle('Begin togglePin06, ...')

  -- Callback Functions ***
  function highTimer06Callback()
    setPinLow(pinNum) 
    lowTimer:start()
  end

  function lowTimer06Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  highTimer = tmr.create()
  lowTimer  = tmr.create()

  -- *** Config Timers ***

  highTimer:register(highTime, tmr.ALARM_SEMI, highTimer06Callback)
  lowTimer:register (lowTime,  tmr.ALARM_SEMI, lowTimer06Callback)

  -- *** Init Pin and Start highTimer***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  highTimer:start()
  
end

-- *** Main Function *** -----------------------------------------------------

function main()
  printTitle('Begin blinky2018nov0204a(),... ')

  -- *** Toggle D4 pin non stop using Timer1 (stop Timer2) ***
  --[[
  pinNum = D4; timerNum = 1; toggleTime = FiveHundredMilliSeconds
  stopTimer(Timer2)
  togglePin04(pinNum, timerNum, toggleTime)
  --]]

  -- *** Toggle D0 pin non stop using Timer2 (stop Timer 1) ***
  --[[
  pinNum = D0; timerNum = 2; toggleTime = OneHundredMilliSeconds
  stopTimer(Timer1)
  togglePin04(pinNum, timerNum, toggleTime)
  --]]

  -- *** Set and Hold D4 pin High***
  --[[
  stopTimer(Timer2)
  pinNum = D4; timerNum = Timer1; highTime = TwoSeconds
  holdPinHigh05(pinNum, timerNum, highTime)
  --]]

  -- *** Set and Hold D4 pin Low***
  --[[
  stopTimer(Timer2)
  pinNum = D4; timerNum = Timer1; lowTime = FourSeconds
  holdPinLow05(pinNum, timerNum, lowTime)
  --]]

  -- *** Toggle D4 Pin ***
  ---[[
  stopTimer(Timer1)
  pinNum = D4; highTime = HalfSecond; lowTime = OneSecond;
  togglePin06(pinNum, highTime, lowTime)
  --]]

end  
-- *** Main *** --------------------------------------------------------------

main()

-- *** End *** ---------------------------------------------------------------

Re: GPIO.input voltage levels vs edge detection

Posted: Sat Nov 03, 2018 3:19 am
by tlfong01
tlfong01 wrote:
Sat Nov 03, 2018 1:58 am
NodeMCU ESPlorer Snippet Writing Notes
Now that I know how to write a basic timer event driven blinky function, I think I should do two things.
1. Improve the blinky program to make it more newbie friendly, ie, making it easy to understand, easy to use, and easy to maintain and expand.
2. Find out how to use this basic blinky program as (a) init.lua

Toggle/Blink/Knock Three Times

Now I have made one more enhancement to the boringly stupid toggle function. Instead of blinking forever, the newbie user can specify how many times to blink.

Sooner I will made one more enhancement, adding a buzzer, for my smart door phone project, and perhaps later adding a robot finger to knock three times on the door.

-- *** Toggle/Knock 3 times D4 Pin using togglePin07 (tmr.ALARM_SEMI) ***
---[[
pinNum = D4; highTime = EighthSecond; lowTime = HalfSecond; toggleCount = 3;
togglePin07(pinNum, highTime, lowTime, toggleCount)
--]]


Knock Three Times - Dawn 1,895,997 views
https://www.youtube.com/watch?v=wT5ms2Nvpco

Code: Select all

-- *** Blinky tlfong01 2018nov *** --

-- *** Title *** -------------------------------------------------------------

title = 'blinky2018nov0302a() tlfong01 2018nov03hkt1054,... '
printTitle(title)

-- *** Globla Variables *** --------------------------------------------------

High   = true
Low    = false

Output = true
Input  = false

Timer1 = 1
Timer2 = 2

D4     = 4
D0     = 0

OneHundredMilliSeconds   = 100
FiveHundredMilliSeconds  = 500
EighthSecond             = 125
FourthSecond             = 250
HalfSecond               = 500
OneSecond                = 1000
TwoSeconds               = 2000
FourSeconds              = 4000

-- *** Debug Print Functions *** ---------------------------------------------

function printTitle(title)
  local threeStars = '***'
  local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'
  local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- *** GPIO Functions *** ----------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

function invertPinLevel(PinLevel)
  if pinLevel == High
    then
      pinLevel = Low
    else
      pinLevel = High
  end
end

-- *** Timer Functions *** ---------------------------------------------------

function stopTimer(timerNum)
  tmr.stop(timerNum)
end

-- *** togglePin04 - Blink LED Non Stop using one tmr.ALARM_Auto timer *** -------------------------------------------------------

function togglePin04(pinNum, timerNum, toggleTime)
  setPinMode(pinNum, Output)
  pinLevel = High

  function togglePin04Callback()
    invertPinLevel(pinLevel)
    setPinLevel(pinNum, pinLevel)
  end

  tmr.alarm(timerNum, toggleTime, tmr.ALARM_AUTO, togglePin04Callback)
end

-- *** togglePin06 - Blink LED Non Stop using two tmr.ALARM_SEMI timers *** -------------------------------------------------------

function togglePin06(pinNum, highTime, lowTime)

  -- Debug Print Statements ***
  printTitle('Begin togglePin06, ...')

  -- Callback Functions ***
  function highTimer06Callback()
    setPinLow(pinNum) 
    lowTimer:start()
  end

  function lowTimer06Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  highTimer = tmr.create()
  lowTimer  = tmr.create()

  -- *** Config Timers ***

  highTimer:register(highTime, tmr.ALARM_SEMI, highTimer06Callback)
  lowTimer:register (lowTime,  tmr.ALARM_SEMI, lowTimer06Callback)

  -- *** Init Pin and Start highTimer***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  highTimer:start()
  
end

-- *** togglePin07 - Blink LED Non Stop using two tmr.ALARM_SEMI timers *** -------------------------------------------------------

function togglePin07(pinNum, highTime, lowTime, toggleCount)

  -- Debug Print Statements ***
  printTitle('Begin togglePin07, ...')

  -- Callback Functions ***
  function highTimer07Callback()
    setPinLow(pinNum) 
    toggleCount = toggleCount - 1
    if toggleCount ~= 0
      then
        lowTimer:start()
      else
	tmr.stop(highTimer)
	tmr.unregister(highTimer)
        tmr.stop(lowTimer)
	tmr.unregister(lowTimer)
    end
  end

  function lowTimer07Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  highTimer = tmr.create()
  lowTimer  = tmr.create()

  -- *** Config Timers ***

  highTimer:register(highTime, tmr.ALARM_SEMI, highTimer07Callback)
  lowTimer:register (lowTime,  tmr.ALARM_SEMI, lowTimer07Callback)

  -- *** Init Pin and Start highTimer***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  highTimer:start()
  
end

-- *** Main Function *** -----------------------------------------------------

function main()

  -- *** Toggle non stop D4 pin using togglePin04(tmr.ALARM_AUTO) ***
  --[[
  pinNum = D4; timerNum = 1; toggleTime = FiveHundredMilliSeconds
  stopTimer(Timer2)
  togglePin04(pinNum, timerNum, toggleTime)
  --]]

  -- *** Toggle non stop D0 pin using togglePin04 (tmr.ALARM_AUTO) ***
  --[[
  pinNum = D0; timerNum = 2; toggleTime = OneHundredMilliSeconds
  stopTimer(Timer1)
  togglePin04(pinNum, timerNum, toggleTime)
  --]]

  -- *** Toggle non stop D4 Pin using togglePin06 (tmr.ALARM_SEMI) ***
  --[[
  stopTimer(Timer1)
  pinNum = D4; highTime = HalfSecond; lowTime = OneSecond;
  togglePin06(pinNum, highTime, lowTime)
  --]]

  -- *** Toggle/Knock 3 times D4 Pin using togglePin07 (tmr.ALARM_SEMI) ***
  ---[[
  stopTimer(Timer1)
  pinNum = D4; highTime = EighthSecond; lowTime = HalfSecond; toggleCount = 3;
  togglePin07(pinNum, highTime, lowTime, toggleCount)
  --]]

end  
-- *** Main *** --------------------------------------------------------------

main()

-- *** End *** ---------------------------------------------------------------

Re: GPIO.input voltage levels vs edge detection

Posted: Sat Nov 03, 2018 2:47 pm
by tlfong01
tlfong01 wrote:
Sat Nov 03, 2018 3:19 am
Blink Three Times

How to blink two pins in sequence

Using procedural python, I can easily blink a pin 3 times, then blink another pin 4 times.

But for event driven NodeMCU Lua, I thought for a while and quickly concluded that it is hard to do that. One possibility is to use coroutines.

One get around is to start two blink functions at the same time, with the first function start immediately, and the second function with a delay which is the estimated time of the first blink job. A blink function with a delay argument would look like below:

function togglePin08(pinNum, delayTime, highTime, lowTime, count)


Code: Select all

-- *** Blinky tlfong01 2018nov *** --

-- *** Title *** -------------------------------------------------------------

title = 'blinky2018nov0304e() tlfong01 2018nov03hkt2233,... '
printTitle(title)

-- *** Globla Variables *** --------------------------------------------------

High   = true
Low    = false

Output = true
Input  = false

D0     = 0
D1     = 1
D2     = 2
D3     = 3
D4     = 4
D5     = 5
D6     = 6
D7     = 7
D8     = 8

OneHundredMilliSeconds   = 100
FiveHundredMilliSeconds  = 500
EighthSecond             = 125
QuarterSecond            = 250
HalfSecond               = 500
OneSecond                = 1000
TwoSeconds               = 2000
FourSeconds              = 4000

OneTime                  = 1
TwoTimes                 = 2 
ThreeTimes               = 3
FourTimes                = 4
EightTimes               = 8

-- *** Debug Print Functions *** ---------------------------------------------

function printTitle(title)
  local threeStars = '***'
  local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'
  local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- *** GPIO Functions *** ----------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

function invertPinLevel(PinLevel)
  if pinLevel == High
    then
      pinLevel = Low
    else
      pinLevel = High
  end
end

-- *** Timer Functions *** ---------------------------------------------------

function stopStaticTimer(timerNum)
  tmr.stop(timerNum)
end

function stopAllStaticTimers()
  for i = 0, 6, 1
    do
      stopStaticTimer(i)
  end
end

-- *** Setup Functions *** ---------------------------------------------------

function setAllPinsOutput()
  for i = 0, 8, 1
    do
      setPinMode(i, Output)
      setPinLow(i)
  end
end

function stopAllTimers()
  stopAllStaticTimers()
end

-- *** Toggle pin functions *** ----------------------------------------------

-- *** togglePin07 - Blink n times *** ---------------------------------------

function togglePin07(pinNum, highTime, lowTime, toggleCount)

  -- Debug Print Statements ***
  printTitle('Begin togglePin07, ...')

  -- Callback Functions ***
  function highTimer07Callback()
    setPinLow(pinNum) 
    toggleCount = toggleCount - 1
    if toggleCount ~= 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
	--[[
	tmr.stop(highTimer)
	tmr.unregister(highTimer)
        tmr.stop(lowTimer)
	tmr.unregister(lowTimer)
	--]]
    end
  end

  function lowTimer07Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  highTimer = tmr.create()
  lowTimer  = tmr.create()

  -- *** Config Timers ***

  highTimer:register(highTime, tmr.ALARM_SEMI, highTimer07Callback)
  lowTimer:register (lowTime,  tmr.ALARM_SEMI, lowTimer07Callback)

  -- *** Init Pin and Start highTimer***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  highTimer:start()
  
end

-- *** togglePin08 - Delay and blink n times *** -----------------------------

function togglePin08(pinNum, delayTime, highTime, lowTime, count)

  -- Debug Print Statements ***
  printTitle('Begin togglePin08, ...')

  -- Callback Functions ***

  function delayTimer08Callback()
    highTimer:start()
  end
  
  function highTimer08Callback()
    setPinLow(pinNum) 
    count = count - 1
    if count ~= 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
    end
  end

  function lowTimer08Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  delayTimer = tmr.create()
  highTimer  = tmr.create()
  lowTimer   = tmr.create()

  -- *** Config Timers ***

  delayTimer:register(delayTime, tmr.ALARM_SINGLE, delayTimer08Callback)
  highTimer :register(highTime,  tmr.ALARM_SEMI,   highTimer08Callback)
  lowTimer  :register (lowTime,  tmr.ALARM_SEMI,   lowTimer08Callback)

  -- *** Init Pin and Start highTimer***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  delayTimer:start()  
end

-- *** Main Function *** -----------------------------------------------------

function main()

  -- *** Setup *** --
  setAllPinsOutput()

  -- *** Toggle D4 pin n times ***
  --[[
  pinNum = D4; highTime = QuarterSecond; lowTime = HalfSecond; toggleCount = EightTimes;
  togglePin07(pinNum, highTime, lowTime, toggleCount)
  --]]

  -- *** Delay then toggle D4 pin n times ***
  ---[[
  pinNum = D4; delayTime = FourSeconds; highTime = QuarterSecond; lowTime = HalfSecond; count = EightTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
  --]]

end  

-- *** Main *** --------------------------------------------------------------

main()

-- *** End *** ---------------------------------------------------------------

Re: GPIO.input voltage levels vs edge detection

Posted: Sun Nov 04, 2018 3:39 am
by tlfong01
tlfong01 wrote:
Sat Nov 03, 2018 2:47 pm
How to blink two pins in sequence

Problem in toggling two same/different pins in sequence

So I wrote 3 snippets (I am using the java/node.js term 'snippet', just to show off, ... :) )

1. Delay 2 seconds, quick blink D4 LED two times.
2. Delay 4 seconds, slow blink D4 LED four times.
3. Delay 4 seconds, slow blink D0 LED four times.


The snippets S1, S2, S3 runs perfectly individually. But if S1 and S2 run together, only S2 runs OK, S1 seems idle or blocked. Same for S1 and S3 running together. My quick and dirty conclusion is that 2 timers cannot work at the same time, ...

--[[ *** D4 pin, Delay 2 seconds, Quick Toggle 2 times ***
pinNum = D4; delayTime = TwoSeconds; highTime = QuarterSecond; lowTime = QuarterSecond; count = TwoTimes;
togglePin08(pinNum, delayTime, highTime, lowTime, count)
--]]


--[[ *** D4 pin, Delay4 seconds, Slow Toggle 4 times ***
pinNum = D4; delayTime = FourSeconds; highTime = HalfSecond; lowTime = HalfSecond; count = FourTimes;
togglePin08(pinNum, delayTime, highTime, lowTime, count)
--]]


---[[ *** D0 pin, Delay4 seconds, Slow Toggle 4 times ***
pinNum = D0; delayTime = FourSeconds; highTime = HalfSecond; lowTime = HalfSecond; count = FourTimes;
togglePin08(pinNum, delayTime, highTime, lowTime, count)
--]]



blinky2018nov0401e

Code: Select all

-- *** Blinky tlfong01 2018nov *** --

-- *** Title *** -------------------------------------------------------------

title = 'blinky2018nov0401e() tlfong01 2018nov04hkt1114,... '
printTitle(title)

-- *** Globla Variables *** --------------------------------------------------

High = true; Low = false

Output = true; Input = false

D0 = 0; D1 = 1; D2 = 2; D3 = 3; D4 = 4; D5 = 5; D6 = 6; D7 = 7; D8 = 8

OneHundredMilliSeconds   =  100; FiveHundredMilliSeconds  =   500
EighthSecond             =  125; QuarterSecond            =   250
HalfSecond               =  500; OneSecond                =  1000
TwoSeconds               = 2000; FourSeconds              =  4000
EightSeconds             = 8000; TenSeconds               = 10000

OneTime = 1; TwoTimes = 2; ThreeTimes = 3; FourTimes = 4; EightTimes = 8

-- *** Debug Print Functions *** ---------------------------------------------

function printTitle(title)
  local threeStars = '***'; local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'; local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- *** GPIO Functions *** ----------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

function invertPinLevel(PinLevel)
  if pinLevel == High
    then
      pinLevel = Low
    else
      pinLevel = High
  end
end

-- *** Timer Functions *** ---------------------------------------------------

function stopStaticTimer(timerNum)
  tmr.stop(timerNum)
end

function stopAllStaticTimers()
  for i = 0, 6, 1
    do
      stopStaticTimer(i)
  end
end

function stopAllTimers()
  stopAllStaticTimers()
end

-- *** Setup Functions *** ---------------------------------------------------

function setAllPinsOutput()
  for i = 0, 8, 1
    do
      setPinMode(i, Output)
  end
end

function setAllPinsLow()
  for i = 0, 8, 1
    do
      setPinLow(i)
  end
end

function setup()
  setAllPinsOutput()
  setAllPinsLow()
end

-- *** Toggle pin functions *** ----------------------------------------------

-- *** togglePin07 - Toggle pin N times *** ---------------------------------------

function togglePin07(pinNum, highTime, lowTime, toggleCount)

  -- Debug Print Statements ***
  printTitle('Begin togglePin07, ...')

  -- Callback Functions ***
  function highTimer07Callback()
    setPinLow(pinNum) 
    toggleCount = toggleCount - 1
    if toggleCount ~= 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
	--[[
	tmr.stop(highTimer)
	tmr.unregister(highTimer)
        tmr.stop(lowTimer)
	tmr.unregister(lowTimer)
	--]]
    end
  end

  function lowTimer07Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  highTimer = tmr.create()
  lowTimer  = tmr.create()

  -- *** Config Timers ***

  highTimer:register(highTime, tmr.ALARM_SEMI, highTimer07Callback)
  lowTimer:register (lowTime,  tmr.ALARM_SEMI, lowTimer07Callback)

  -- *** Init Pin and Start highTimer***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  highTimer:start()
  
end

-- *** togglePin08 - Delayed toggle pin n times *** -----------------------------

function togglePin08(pinNum, delayTime, highTime, lowTime, count)

  -- Debug Print Statements ***
  printTitle('Begin togglePin08, ...')

  -- Callback Functions ***

  function delayTimer08Callback()
    setPinHigh(pinNum)
    highTimer:start()
  end
  
  function highTimer08Callback()
    setPinLow(pinNum) 
    count = count - 1
    if count ~= 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
    end
  end

  function lowTimer08Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  delayTimer = tmr.create()
  highTimer  = tmr.create()
  lowTimer   = tmr.create()

  -- *** Config Timers ***

  delayTimer:register(delayTime, tmr.ALARM_SINGLE, delayTimer08Callback)
  highTimer :register(highTime,  tmr.ALARM_SEMI,   highTimer08Callback)
  lowTimer  :register(lowTime,   tmr.ALARM_SEMI,   lowTimer08Callback)

  -- *** Action ***
  delayTimer:start()  
end

-- *** Main Function *** -----------------------------------------------------

function main()

  -- *** Setup *** --
  setup()

  --[[ *** D4 pin, Immediately Toggle 8 times ***
  pinNum = D4; highTime = QuarterSecond; lowTime = HalfSecond; toggleCount = EightTimes;
  togglePin07(pinNum, highTime, lowTime, toggleCount)
  --]]

  --[[ *** D4 pin, Delay 4 seconds, Toggle 8 times ***
  pinNum = D4; delayTime = FourSeconds; highTime = QuarterSecond; lowTime = HalfSecond; count = EightTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
  --]]

  --[[ *** D4 pin, Delay 2 seconds, Quick Toggle 2 times ***
  pinNum = D4; delayTime = TwoSeconds; highTime = QuarterSecond; lowTime = QuarterSecond; count = TwoTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
  --]]

  --[[ *** D4 pin, Delay4 seconds, Slow Toggle 4 times ***
  pinNum = D4; delayTime = FourSeconds; highTime = HalfSecond; lowTime = HalfSecond; count = FourTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
  --]]

  ---[[ *** D0 pin, Delay4 seconds, Slow Toggle 4 times ***
  pinNum = D0; delayTime = FourSeconds; highTime = HalfSecond; lowTime = HalfSecond; count = FourTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
  --]]

end  

-- *** Main *** --------------------------------------------------------------

main()

-- *** End *** ---------------------------------------------------------------

Re: GPIO.input voltage levels vs edge detection

Posted: Sun Nov 04, 2018 8:22 am
by tlfong01
tlfong01 wrote:
Sun Nov 04, 2018 3:39 am
tlfong01 wrote:
Sat Nov 03, 2018 2:47 pm
How to blink two pins in sequence
Problem in toggling two same/different pins in sequence

Problems in using static counters and dynamic counter at the same time

I wasted 2 hours trying to active 2 timers at the same time, one static, one dynamic, and ended up with a big mess.

My quick and dirty conclusion is that NodeMCU static timers are buggy,

Perhaps that is why NodeMCU is saying that it will become obsolete.

Any way, I gave up digging further in NodeMCU timers. I am thinking of trying I2C RTC DH3231 Real Clock Timers first, ...

The following functions are working OK, if run individually.

--p4_d0_h250_l500_c8() -- Pin4, Delay 0 seconds, Slow toggle, 8 times
--p4_d4_h250_l500_c8() -- Pin4, Delay 4 seconds, Slow toggle, 8 times
--p4_d2_h250_l250_c2() -- Pin4, Delay 2 seconds, Fast toggle, 2 times
--p0_d2_h250_l250_c4() -- Pin0, Delay 2 seconds, Fast toggle, 4 times



Code: Select all

-- *** Blinky tlfong01 2018nov *** --

-- *** Title *** -------------------------------------------------------------

title = 'blinky2018nov0404a() tlfong01 2018nov04hkt1609,... '
printTitle(title)

-- *** Globla Variables *** --------------------------------------------------

High = true; Low = false

Output = true; Input = false

D0 = 0; D1 = 1; D2 = 2; D3 = 3; D4 = 4; D5 = 5; D6 = 6; D7 = 7; D8 = 8

OneHundredMilliSeconds   =  100; FiveHundredMilliSeconds  =   500
EighthSecond             =  125; QuarterSecond            =   250
HalfSecond               =  500; OneSecond                =  1000
TwoSeconds               = 2000; FourSeconds              =  4000
EightSeconds             = 8000; TenSeconds               = 10000

OneTime = 1; TwoTimes = 2; ThreeTimes = 3; FourTimes = 4; EightTimes = 8

-- *** Debug Print Functions *** ---------------------------------------------

function printTitle(title)
  local threeStars = '***'; local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'; local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- *** GPIO Functions *** ----------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

function invertPinLevel(PinLevel)
  if pinLevel == High
    then
      pinLevel = Low
    else
      pinLevel = High
  end
end

-- *** Static Timer Functions *** ---------------------------------------------------

function stopStaticTimer(timerNum)
  tmr.stop(timerNum)
end

function stopAllStaticTimers()
  for i = 0, 6, 1
    do
      stopStaticTimer(i)
  end
end

-- *** Setup Functions *** ---------------------------------------------------

function setAllPinsOutput()
  for i = 0, 8, 1
    do
      setPinMode(i, Output)
  end
end

function setAllPinsLow()
  for i = 0, 8, 1
    do
      setPinLow(i)
  end
end

function setupPins()
  setAllPinsOutput()
  setAllPinsLow()
end

-- *** Toggle pin functions *** ----------------------------------------------

-- *** togglePin07 - Toggle pin N times *** ---------------------------------------

function togglePin07(pinNum, highTime, lowTime, toggleCount)

  -- Debug Print Statements ***
  printTitle('Begin togglePin07, ...')

  -- Callback Functions ***
  function highTimer07Callback()
    setPinLow(pinNum) 
    toggleCount = toggleCount - 1
    if toggleCount ~= 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
	--[[
	tmr.stop(highTimer)
	tmr.unregister(highTimer)
        tmr.stop(lowTimer)
	tmr.unregister(lowTimer)
	--]]
    end
  end

  function lowTimer07Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  highTimer = tmr.create()
  lowTimer  = tmr.create()

  -- *** Config Timers ***

  highTimer:register(highTime, tmr.ALARM_SEMI, highTimer07Callback)
  lowTimer:register (lowTime,  tmr.ALARM_SEMI, lowTimer07Callback)

  -- *** Init Pin and Start highTimer***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  highTimer:start()
  
end

-- *** togglePin08 - Delayed toggle pin n times *** -----------------------------

function togglePin08(pinNum, delayTime, highTime, lowTime, count)

  -- Debug Print Statements ***
  printTitle('Begin togglePin08, ...')

  -- Callback Functions ***

  function delayTimer08Callback()
    setPinHigh(pinNum)
    highTimer:start()
  end
  
  function highTimer08Callback()
    setPinLow(pinNum) 
    count = count - 1
    if count ~= 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
    end
  end

  function lowTimer08Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  delayTimer = tmr.create()
  highTimer  = tmr.create()
  lowTimer   = tmr.create()

  -- *** Config Timers ***

  delayTimer:register(delayTime, tmr.ALARM_SINGLE, delayTimer08Callback)
  highTimer :register(highTime,  tmr.ALARM_SEMI,   highTimer08Callback)
  lowTimer  :register(lowTime,   tmr.ALARM_SEMI,   lowTimer08Callback)

  -- *** Action ***
  delayTimer:start()  
end

-- *** Test Functions *** ----------------------------------------------------

function test_PinD4_DelayZero_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
  pinNum = D4; highTime = QuarterSecond; lowTime = HalfSecond; toggleCount = EightTimes;
  togglePin07(pinNum, highTime, lowTime, toggleCount)
end

function test_PinD4_DelayFourSeconds_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
  pinNum = D4; delayTime = FourSeconds; highTime = QuarterSecond; lowTime = HalfSecond; count = EightTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
end

function test_PinD4_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountTwoTimes()
  pinNum = D4; delayTime = TwoSeconds; highTime = QuarterSecond; lowTime = QuarterSecond; count = TwoTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
end

function test_PinD0_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountFourTimes()
  pinNum = D0; delayTime = TwoSeconds; highTime = QuarterSecond; lowTime = QuarterSecond; count = FourTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
end

-- *** Test Functions with Short Names *** -------------------------------------------------------

function p4_d0_h250_l500_c8()
  test_PinD4_DelayZero_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
end

function p4_d4_h250_l500_c8()
  test_PinD4_DelayFourSeconds_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
end

function p4_d2_h250_l250_c2()
  test_PinD4_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountTwoTimes()
end

function p0_d2_h250_l250_c4()
  test_PinD0_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountFourTimes()
end

-- *** Main Function *** -----------------------------------------------------

function main()

  -- *** Setup *** --
  setupPins()
  stopAllStaticTimers()

  --p4_d0_h250_l500_c8()  -- Pin4, Delay 0 seconds, Slow toggle, 8 times
  --p4_d4_h250_l500_c8()  -- Pin4, Delay 4 seconds, Slow toggle, 8 times
  --p4_d2_h250_l250_c2()  -- Pin4, Delay 2 seconds, Fast toggle, 2 times
  --p0_d2_h250_l250_c4()  -- Pin0, Delay 2 seconds, Fast toggle, 4 times
end  

-- *** Main *** --------------------------------------------------------------

main()

-- *** End *** ---------------------------------------------------------------

Re: GPIO.input voltage levels vs edge detection

Posted: Mon Nov 05, 2018 8:52 am
by tlfong01
tlfong01 wrote:
Sun Nov 04, 2018 8:22 am
Problems in using static counters and dynamic counter at the same time
I wasted 2 hours trying to active 2 timers at the same time, one static, one dynamic, and ended up with a big mess.
My quick and dirty conclusion is that NodeMCU static timers are buggy.

Blinky program to do four blink tasks in sequence

Now I have finished debugging a program to do the following:

1. Starts a schedule timer, which after a specified delay, will do a specified number of toggle pin tasks.

2. Each pin toggle task starts with a specified delay, toggle pin a specified number of times, with specified High time and Low times.

Next step is to improve the program to toggle different pins with different specified count, high and low time.

---[[
taskCount = FourTasks; taskDelayTime = HalfSecond
pinNum = D4; toggleDelayTime = HalfSecond; highTime = QuarterSecond; lowTime = QuarterSecond; toggleCount = TwoTimes;
togglePin09(taskCount, taskDelayTime, pinNum, toggleDelayTime, highTime, lowTime, toggleCount)
--]]

Code: Select all

-- ---------------------------------------------------------------------------
-- *** Blinky tlfong01 2018nov *** --
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** Title *** --
-- ---------------------------------------------------------------------------

title = 'blinky2018nov0502d() tlfong01 2018nov05hkt1633,... '
printTitle(title)

-- ---------------------------------------------------------------------------
-- *** Globla Variables *** --
-- ---------------------------------------------------------------------------

High = true; Low = false

Output = true; Input = false

D0 = 0; D1 = 1; D2 = 2; D3 = 3; D4 = 4; D5 = 5; D6 = 6; D7 = 7; D8 = 8

OneHundredMilliSeconds   =  100; FiveHundredMilliSeconds  =   500
EighthSecond             =  125; QuarterSecond            =   250
HalfSecond               =  500; OneSecond                =  1000
TwoSeconds               = 2000; FourSeconds              =  4000
EightSeconds             = 8000; TenSeconds               = 10000

OneTime = 1; TwoTimes = 2; ThreeTimes = 3; FourTimes = 4; EightTimes = 8

OneTask = 1' TwoTasks = 2; ThreeTasks = 3;  FourTasks = 4

-- ---------------------------------------------------------------------------
-- *** Debug Print Functions *** --
-- ---------------------------------------------------------------------------

function printTitle(title)
  local threeStars = '***'; local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'; local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- ---------------------------------------------------------------------------
-- *** GPIO Functions *** --
-- ---------------------------------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

function invertPinLevel(PinLevel)
  if pinLevel == High
    then
      pinLevel = Low
    else
      pinLevel = High
  end
end

-- ---------------------------------------------------------------------------
-- *** Static Timer Functions *** --
-- ---------------------------------------------------------------------------

function stopStaticTimer(timerNum)
  tmr.stop(timerNum)
end

function stopAllStaticTimers()
  for i = 0, 6, 1
    do
      stopStaticTimer(i)
  end
end

-- ---------------------------------------------------------------------------
-- *** Setup Functions *** --
-- ---------------------------------------------------------------------------

function setAllPinsOutput()
  for i = 0, 8, 1
    do
      setPinMode(i, Output)
  end
end

function setAllPinsLow()
  for i = 0, 8, 1
    do
      setPinLow(i)
  end
end

function setupPins()
  setAllPinsOutput()
  setAllPinsLow()
end

-- ---------------------------------------------------------------------------
-- *** Toggle pin functions *** --
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** togglePin07 - Toggle pin N times *** --
-- ---------------------------------------------------------------------------

function togglePin07(pinNum, highTime, lowTime, toggleCount)

  -- Debug Print Statements ***
  printTitle('Begin togglePin07, ...')

  -- Callback Functions ***
  function highTimer07Callback()
    setPinLow(pinNum) 
    toggleCount = toggleCount - 1
    if toggleCount ~>= 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
	--[[
	tmr.stop(highTimer)
	tmr.unregister(highTimer)
        tmr.stop(lowTimer)
	tmr.unregister(lowTimer)
	--]]
    end
  end

  function lowTimer07Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  highTimer = tmr.create()
  lowTimer  = tmr.create()

  -- *** Config Timers ***

  highTimer:register(highTime, tmr.ALARM_SEMI, highTimer07Callback)
  lowTimer:register (lowTime,  tmr.ALARM_SEMI, lowTimer07Callback)

  -- *** Init Pin and Start highTimer***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  highTimer:start()
  
end

-- ---------------------------------------------------------------------------
-- *** togglePin08 - Delayed toggle pin n times *** --
-- ---------------------------------------------------------------------------

function togglePin08(pinNum, toggleDelayTime, highTime, lowTime, count)

  -- Debug Print Statements ***
  printTitle('Begin togglePin08, ...')

  -- Callback Functions ***

  function delayTimer08Callback()
    setPinHigh(pinNum)
    highTimer:start()
  end
  
  function highTimer08Callback()
    setPinLow(pinNum) 
    count = count - 1
    if count ~> 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
    end
  end

  function lowTimer08Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  delayTimer = tmr.create()
  highTimer  = tmr.create()
  lowTimer   = tmr.create()

  -- *** Config Timers ***

  delayTimer:register(toggleDelayTime, tmr.ALARM_SINGLE, delayTimer08Callback)
  highTimer :register(highTime,  tmr.ALARM_SEMI,   highTimer08Callback)
  lowTimer  :register(lowTime,   tmr.ALARM_SEMI,   lowTimer08Callback)

  -- *** Action ***
  delayTimer:start()  
end

-- ---------------------------------------------------------------------------
-- *** togglePin09 - Toggle Pin Scheduling Timer *** --
-- ---------------------------------------------------------------------------

function togglePin09(taskCount, taskDelayTime, pinNum, toggleDelayTime, highTime, lowTime, toggleCount)

  -- Debug Print Statements ***
  printTitle('Begin togglePin09, ...')

  -- Callback Functions ***

  function scheduleTimer09Callback()
    taskCount = taskCount - 1
    if taskCount ~>= 0
      then
        delayTimer:start()
      else
        scheduleTimer:stop()
    end
  end

  function delayTimer09Callback()
    setPinHigh(pinNum)
    tempCount = toggleCount
    --tempCount = 5
    highTimer:start()
  end
  
  function highTimer09Callback()
    delayTimer:stop()
    setPinLow(pinNum) 
    tempCount = tempCount - 1
    if tempCount ~>= 0
      then
        lowTimer:start()
      else        
        highTimer:stop()
	lowTimer:stop()
        scheduleTimer:start()
    end
  end

  function lowTimer09Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  scheduleTimer = tmr.create()
  delayTimer = tmr.create()
  highTimer  = tmr.create()
  lowTimer   = tmr.create()

  -- *** Config Timers ***
  scheduleTimer:register(taskDelayTime, tmr.ALARM_SEMI, scheduleTimer09Callback)
  delayTimer:register(toggleDelayTime, tmr.ALARM_SEMI, delayTimer09Callback)
  highTimer :register(highTime,  tmr.ALARM_SEMI,   highTimer09Callback)
  lowTimer  :register(lowTime,   tmr.ALARM_SEMI,   lowTimer09Callback)

  -- *** Action ***
  scheduleTimer:start()    
end

-- ---------------------------------------------------------------------------
-- *** Test Functions *** --
-- ---------------------------------------------------------------------------

function test_PinD4_DelayZero_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
  pinNum = D4; highTime = QuarterSecond; lowTime = HalfSecond; toggleCount = EightTimes;
  togglePin07(pinNum, highTime, lowTime, toggleCount)
end

function test_PinD4_DelayFourSeconds_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
  pinNum = D4; toggleDelayTime = FourSeconds; highTime = QuarterSecond; lowTime = HalfSecond; count = EightTimes;
  togglePin08(pinNum, toggleDelayTime, highTime, lowTime, count)
end

function test_PinD4_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountTwoTimes()
  pinNum = D4; toggleDelayTime = TwoSeconds; highTime = QuarterSecond; lowTime = QuarterSecond; count = TwoTimes;
  togglePin08(pinNum, toggleDelayTime, highTime, lowTime, count)
end

function test_PinD0_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountFourTimes()
  pinNum = D0; toggleDelayTime = TwoSeconds; highTime = QuarterSecond; lowTime = QuarterSecond; count = FourTimes;
  togglePin08(pinNum, toggleDelayTime, highTime, lowTime, count)
end

-- *** Test Functions with Short Names *** --

function p4_d0_h250_l500_c8()
  test_PinD4_DelayZero_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
end

function p4_d4_h250_l500_c8()
  test_PinD4_DelayFourSeconds_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
end

function p4_d2_h250_l250_c2()
  test_PinD4_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountTwoTimes()
end

function p0_d2_h250_l250_c4()
  test_PinD0_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountFourTimes()
end

-- ---------------------------------------------------------------------------
-- *** Main Function *** -----------------------------------------------------
-- ---------------------------------------------------------------------------

function main()

  -- *** Setup *** --
  setupPins()
  stopAllStaticTimers()

  --p4_d0_h250_l500_c8()  -- Pin4, Delay 0 seconds, Slow toggle, 8 times
  --p4_d4_h250_l500_c8()  -- Pin4, Delay 4 seconds, Slow toggle, 8 times
  --p4_d2_h250_l250_c2()  -- Pin4, Delay 2 seconds, Fast toggle, 2 times
  --p0_d2_h250_l250_c4()  -- Pin0, Delay 2 seconds, Fast toggle, 4 times

  ---[[
  taskCount = FourTasks; taskDelayTime = HalfSecond
  pinNum = D4; toggleDelayTime = HalfSecond; highTime = QuarterSecond; lowTime = QuarterSecond; toggleCount = TwoTimes;
  togglePin09(taskCount, taskDelayTime, pinNum, toggleDelayTime, highTime, lowTime, toggleCount)
  --]]

end

end  

-- ---------------------------------------------------------------------------
-- *** Main *** --------------------------------------------------------------
-- ---------------------------------------------------------------------------

main()

-- ---------------------------------------------------------------------------
-- *** End *** --
-- ---------------------------------------------------------------------------

Re: GPIO.input voltage levels vs edge detection

Posted: Tue Nov 06, 2018 2:42 am
by tlfong01
tlfong01 wrote:
Mon Nov 05, 2018 8:52 am
Blinky program to do four blink tasks in sequence
Now I have finished debugging a program to do the following:
1. Starts a schedule timer, which after a specified delay, will do a specified number of toggle pin tasks.
2. Each pin toggle task starts with a specified delay, toggle pin a specified number of times, with specified High time and Low times.
Next step is to improve the program to toggle different pins with different specified count, high and low time.

Newbie Blink Selfie Walking Through Notes

So I have completed the basic blinky program. The program is getting a bit too long to maintain. I started with version 1, then 2, ... until version 9 now. Every time I found a new built OK, I would keep the most recent two or three, and delete the more ancient ones. I keep changing function names, and adding more arguments, and then found I forgot which version has how many, and which arguments.

I miss the Arduino C++'s amphorous function thing, where I can keep the function name no change, and just change the type and number of arguments.

I also miss the Rpi python's dynamic typing, and named arguments.

Lua sadly, does not have amphorous functions nor named arguments. I
I googled and found Lua has a get around, ie, using table as a singled argument which hides all different arguments inside.

I think this using table as one and only one argument is good because it also obeys the open and close principle (Bertrand Meyer 1988) (see Uncle Bob's article below).

However, the table argument trick requires the os package. I tried it but found the os package is not included in NodeMCU! :(

Lua's get around of named arguments
https://www.lua.org/pil/5.3.html

5.3 – Named Arguments
The parameter passing mechanism in Lua is positional...
Sometimes, however, it is useful to specify the arguments by name ...
Lua has no direct support for that syntax, but we can have the same final effect, with a small syntax change. The idea here is to pack all arguments into a table and use that table as the only argument to the function. ...

Accordingly, we define rename with only one parameter and get the actual arguments from this parameter:
function rename (arg)
return os.rename(arg.old, arg.new)
end

This style of parameter passing is especially helpful when the function has many parameters, and most of them are optional. For instance ...

The Open Closed Principle - Uncle Bob 2014may12
https://blog.cleancoder.com/uncle-bob/2 ... ciple.html

Newbie Blink Program Version 0601 (working but dirty!)

Code: Select all

-- ---------------------------------------------------------------------------
-- *** Blinky tlfong01 2018nov *** --
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** Title *** --
-- ---------------------------------------------------------------------------

title = 'blinky2018nov0601a() tlfong01 2018nov06hkt0952,... '
printTitle(title)

-- ---------------------------------------------------------------------------
-- *** Globla Variables *** --
-- ---------------------------------------------------------------------------

High = true; Low = false

Output = true; Input = false

D0 = 0; D1 = 1; D2 = 2; D3 = 3; D4 = 4; D5 = 5; D6 = 6; D7 = 7; D8 = 8

OneHundredMilliSeconds   =  100; FiveHundredMilliSeconds  =   500
EighthSecond             =  125; QuarterSecond            =   250
HalfSecond               =  500; OneSecond                =  1000
TwoSeconds               = 2000; FourSeconds              =  4000
EightSeconds             = 8000; TenSeconds               = 10000

OneTime = 1; TwoTimes = 2; ThreeTimes = 3; FourTimes = 4; EightTimes = 8

-- ---------------------------------------------------------------------------
-- *** Debug Print Functions *** --
-- ---------------------------------------------------------------------------

function printTitle(title)
  local threeStars = '***'; local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'; local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- ---------------------------------------------------------------------------
-- *** GPIO Functions *** --
-- ---------------------------------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

function invertPinLevel(PinLevel)
  if pinLevel == High
    then
      pinLevel = Low
    else
      pinLevel = High
  end
end

-- ---------------------------------------------------------------------------
-- *** Static Timer Functions *** --
-- ---------------------------------------------------------------------------

function stopStaticTimer(timerNum)
  tmr.stop(timerNum)
end

function stopAllStaticTimers()
  for i = 0, 6, 1
    do
      stopStaticTimer(i)
  end
end

-- ---------------------------------------------------------------------------
-- *** Setup Functions *** --
-- ---------------------------------------------------------------------------

function setAllPinsOutput()
  for i = 0, 8, 1
    do
      setPinMode(i, Output)
  end
end

function setAllPinsLow()
  for i = 0, 8, 1
    do
      setPinLow(i)
  end
end

function setupPins()
  setAllPinsOutput()
  setAllPinsLow()
end

-- ---------------------------------------------------------------------------
-- *** Toggle pin functions *** --
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** togglePin07 - Toggle pin N times using highTimer and lowTimer *** --
-- ---------------------------------------------------------------------------

function togglePin07(pinNum, highTime, lowTime, toggleCount)

  -- Debug Print Statements ***
  printTitle('Begin togglePin07, ...')

  -- Callback Functions ***
  function highTimer07Callback()
    setPinLow(pinNum) 
    toggleCount = toggleCount - 1
    if toggleCount ~= 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
    end
  end

  function lowTimer07Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  highTimer = tmr.create()
  lowTimer  = tmr.create()

  -- *** Config Timers ***

  highTimer:register(highTime, tmr.ALARM_SEMI, highTimer07Callback)
  lowTimer:register (lowTime,  tmr.ALARM_SEMI, lowTimer07Callback)

  -- *** Action ***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  highTimer:start()
  
end

-- ---------------------------------------------------------------------------
-- *** togglePin08 - toggle pin n times with an additional delayTimer *** --
-- ---------------------------------------------------------------------------

function togglePin08(pinNum, delayTime, highTime, lowTime, count)

  -- Debug Print Statements ***
  printTitle('Begin togglePin08, ...')

  -- Callback Functions ***

  function delayTimer08Callback()
    setPinHigh(pinNum)
    highTimer:start()
  end
  
  function highTimer08Callback()
    setPinLow(pinNum) 
    count = count - 1
    if count ~= 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
    end
  end

  function lowTimer08Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  delayTimer = tmr.create()
  highTimer  = tmr.create()
  lowTimer   = tmr.create()

  -- *** Config Timers ***

  delayTimer:register(delayTime, tmr.ALARM_SINGLE, delayTimer08Callback)
  highTimer :register(highTime,  tmr.ALARM_SEMI,   highTimer08Callback)
  lowTimer  :register(lowTime,   tmr.ALARM_SEMI,   lowTimer08Callback)

  -- *** Action ***
  delayTimer:start()  
end

-- ---------------------------------------------------------------------------
-- *** togglePin09 - Toggle Pin additional delayTimer and scheduleTimer *** --
-- ---------------------------------------------------------------------------

function togglePin09(taskCount, taskDelayTime, pinNum, delayTime, highTime, lowTime, count)

  -- Debug Print Statements ***
  printTitle('Begin togglePin09, ...')

  -- Callback Functions ***

  function scheduleTimer09Callback()
    taskCount = taskCount - 1
    if taskCount >= 0 
      then
        delayTimer:start()
      else
        scheduleTimer:stop()
    end
  end

  function delayTimer09Callback()
    setPinHigh(pinNum)
    tempCount = count
    highTimer:start()
  end
  
  function highTimer09Callback()
    setPinLow(pinNum) 
    tempCount = tempCount - 1
    if tempCount > 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	lowTimer:stop()
	scheduleTimer:start()
    end
  end

  function lowTimer09Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  scheduleTimer = tmr.create()
  delayTimer    = tmr.create()
  highTimer     = tmr.create()
  lowTimer      = tmr.create()

  -- *** Config Timers ***
  scheduleTimer:register(taskDelayTime, tmr.ALARM_SEMI, scheduleTimer09Callback)
  delayTimer:register(delayTime, tmr.ALARM_SEMI, delayTimer09Callback)
  highTimer :register(highTime,  tmr.ALARM_SEMI,   highTimer09Callback)
  lowTimer  :register(lowTime,   tmr.ALARM_SEMI,   lowTimer09Callback)

  -- *** Action ***
  scheduleTimer:start()    
end

-- ---------------------------------------------------------------------------
-- *** Test Functions *** --
-- ---------------------------------------------------------------------------

--p4_d0_h250_l500_c8()  -- Pin4, Delay 0 seconds, Slow toggle, 8 times
function test_PinD4_DelayZero_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
  pinNum = D4; highTime = QuarterSecond; lowTime = HalfSecond; toggleCount = EightTimes;
  togglePin07(pinNum, highTime, lowTime, toggleCount)
end

function p4_d0_h250_l500_c8()
  test_PinD4_DelayZero_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
end

--p4_d4_h250_l500_c8()  -- Pin4, Delay 4 seconds, Slow toggle, 8 times
function test_PinD4_DelayFourSeconds_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
  pinNum = D4; delayTime = FourSeconds; highTime = QuarterSecond; lowTime = HalfSecond; count = EightTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
end

function p4_d4_h250_l500_c8()
  test_PinD4_DelayFourSeconds_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
end

--p4_d2_h250_l250_c2()  -- Pin4, Delay 2 seconds, Fast toggle, 2 times
function test_PinD4_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountTwoTimes()
  pinNum = D4; delayTime = TwoSeconds; highTime = QuarterSecond; lowTime = QuarterSecond; count = TwoTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
end

function p4_d2_h250_l250_c2()
  test_PinD4_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountTwoTimes()
end

--p0_d2_h250_l250_c4()  -- Pin0, Delay 2 seconds, Fast toggle, 4 times
function test_PinD0_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountFourTimes()
  pinNum = D0; delayTime = TwoSeconds; highTime = QuarterSecond; lowTime = QuarterSecond; count = FourTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
end

function p0_d2_h250_l250_c4()
  test_PinD0_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountFourTimes()
end

-- ---------------------------------------------------------------------------
-- *** Main Function *** -----------------------------------------------------
-- ---------------------------------------------------------------------------

function main()

  -- *** Setup *** --
  setupPins()
  stopAllStaticTimers()

  --p4_d0_h250_l500_c8()  -- Pin4, Delay 0 seconds, Slow toggle, 8 times
  --p4_d4_h250_l500_c8()  -- Pin4, Delay 4 seconds, Slow toggle, 8 times
  --p4_d2_h250_l250_c2()  -- Pin4, Delay 2 seconds, Fast toggle, 2 times
  --p0_d2_h250_l250_c4()  -- Pin0, Delay 2 seconds, Fast toggle, 4 times

  taskCount = FourTimes; taskDelayTime = HalfSecond
  pinNum = D4; delayTime = OneSecond; highTime = QuarterSecond; lowTime = QuarterSecond; count = TwoTimes;
  togglePin09(taskCount, taskDelayTime, pinNum, delayTime, highTime, lowTime, count)
end

-- ---------------------------------------------------------------------------
-- *** Main *** --------------------------------------------------------------
-- ---------------------------------------------------------------------------

main()

end  

-- ---------------------------------------------------------------------------
-- *** End *** --
-- ---------------------------------------------------------------------------

Re: GPIO.input voltage levels vs edge detection

Posted: Tue Nov 06, 2018 9:14 am
by tlfong01
Newbie Blink Selfie Walking Through Notes

NodeMCU Board Troubleshooting Power Reset Tip

This morning I spent one hour troubleshooting my new version of newebie blink. I found intermittent failures in saving my program. I had a couple of identical software copies of a working program and saved them for troubleshooting. I modified one version to test out things and found that I had likely messed up the ESPLorer RAM. I tried many things like erase flash, software reset, hardware reset, restart ESPlorer, changing USB cables, changing NodeMCU boards (yes, I have 8 boards (of different versions/models of Amica and Wmos from two reputalbe TaoBao shops and 4 USB cables on table and swap any board in 5 seconds). I even wrongly cursed the ESPlorer software and was about to reinstall it. But then luckily I noticed that the Amica board has a big SMD 100uF cap. I never saw such big caps on smalls boards. I suddenly recollect one of the ESP8266 troubleshooting tips I read some weeks ago:

Power reset the ESP8266 chip (unplug USB cable) and wait for a couple of seconds before repower again. One thing I guess I missed is that if the transient filtering cap is big, then perhaps a couple of seconds is not long enough to discharge the cap to a low level to hardware reset the ESP8266.

So from now on I should respect the little 100uF capacitor more and wait for at least three minutes for it to happily discharge, before resetting!

Anyway, I solved the intermittent bug and concluded that I was not smart enough to have noticed something important (and two hours wasted!) :(

Re: GPIO.input voltage levels vs edge detection

Posted: Tue Nov 06, 2018 2:22 pm
by tlfong01
tlfong01 wrote:
Tue Nov 06, 2018 9:14 am
Newbie Blink Selfie Walking Through Notes
NodeMCU Board Troubleshooting Power Reset Tip

Using table as function argument, according to open close principle

So to avoid the following error prone way of calling functions with so many agrguments, I use instead, table as one and only one argument.

--[[
taskCount = FourTimes; taskDelayTime = HalfSecond
pinNum = D4; delayTime = OneSecond; highTime = QuarterSecond; lowTime = QuarterSecond; count = TwoTimes;
togglePin09(taskCount, taskDelayTime, pinNum, delayTime, highTime, lowTime, count)
--]]


Two pin table definitions and the new one argument function, are listed below.

-- ---------------------------------------------------------------------------
-- *** togglePin10 - using argument PinTbl and BlinkTbl *** --
-- ---------------------------------------------------------------------------

pinTbl01 = {}
pinTbl01.taskCount = FourTimes
pinTbl01.taskDelayTime = HalfSecond
pinTbl01.pinNum = D4
pinTbl01.delayTime = OneSecond
pinTbl01.highTime = QuarterSecond
pinTbl01.lowTime = QuarterSecond
pinTbl01.toggleCount = TwoTimes

pinTbl02 = {
taskCount = FourTimes
taskDelayTime = HalfSecond
pinNum = D4
delayTime = OneSecond
highTime = QuarterSecond
lowTime = QuarterSecond
toggleCount = TwoTimes
}

function newbieBlink10(pinTbl)

taskCount = pinTbl.taskCount
taskDelayTime = pinTbl.taskDelayTime
pinNum = pinTbl.pinNum
delayTime = pinTbl.delayTime
highTime = pinTbl.highTime
lowTime = pinTbl.lowTime
toggleCount = pinTbl.toggleCount

togglePin09(taskCount, taskDelayTime, pinNum, delayTime, highTime, lowTime, count)


end

Now I can call the new function with only one table argument.

newbieBlink10(pinTbl01)

The new function version 10 does the same job as version 9, except the argument thing. Version 10 inputs the table and gets the many arguments from the table, and call version 9 to do the old job. I couldn't believe it the new function ran perfectly the first time. I ran it second time and also no problem.

So I was about to call it day.

But sadly the non believer ran it the third time, and this third time seemed to have corrupted the RAM. Did I generate too much garbage by just two runs? I dug deeper and found a weird thing that I did not know that I did not know, ... :cry:

Lua brilhando em nove continentes - 348,179 views
https://www.youtube.com/watch?v=A9Naq9H_7QA

The moon looks down innocently from the sky,
uncomphrehending at the joys and woes that it sees in the world below;
How many couples are sitting by the hearth, their heart filled with joy,
and how many couples are scattered far and wide in this cruel and uncaring world.

Re: GPIO.input voltage levels vs edge detection

Posted: Wed Nov 07, 2018 4:22 am
by tlfong01
tlfong01 wrote:
Tue Nov 06, 2018 2:22 pm
Newbie Blink Selfie Walking Through Notes
NodeMCU Board Troubleshooting Power Reset Tip
Using table as function argument, according to open close principle

NewbieBlink Version 10 Using Pin Table Argument Working OK

I found program Version 10 using snippets of Version 7, 8, 9, 10 all working OK. The main function is listed below.

function main()
-- *** Setup *** --
setupPins()
stopAllStaticTimers()
--p4_d0_h250_l500_c8() -- Pin4, Delay 0 seconds, Slow toggle, 8 times
--p4_d4_h250_l500_c8() -- Pin4, Delay 4 seconds, Slow toggle, 8 times
--p4_d2_h250_l250_c2() -- Pin4, Delay 2 seconds, Fast toggle, 2 times
--p0_d2_h250_l250_c4() -- Pin0, Delay 2 seconds, Fast toggle, 4 times
--[[
taskCount = FourTimes; taskDelayTime = HalfSecond
pinNum = D4; delayTime = OneSecond; highTime = QuarterSecond; lowTime = QuarterSecond; count = TwoTimes;
togglePin09(taskCount, taskDelayTime, pinNum, delayTime, highTime, lowTime, count)
--]]
--newbieBlink10(pinTbl01)
end

I have made a backup this Version 10 program in a zipped file, and will use the extracted copies as work copies for future testing.

This is sort of stable, minimal, verifiable program which I have repeatedly tested on two WeMos D1 Mini. I will also soon test this version on the remaining 6 Wemos and Amica NodeMCU ESP8066-12x evaluation boards.

I decided to pause at this point to backup and document, because I found that I seemed to hit a block. I did a little bit more modification to hardware or software, I found intermittent, unrepeatable, unexplainable, weird errors.

Of course I cannot explain the weird things mainly because I don't have enough knowledge in ESP8266 hardware, and event driven programming.

Anyway, I will take a break at this milestone, thinking what to do next, ...

I have listed the stable version 10 below.


Code: Select all

-- ---------------------------------------------------------------------------
-- *** Newbie Blinky Version 10 2018nov0701a tlfong01 2018nov *** --
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** Title *** --
-- ---------------------------------------------------------------------------

title = 'blinky2018nov0701a() tlfong01 2018nov07hkt1137'
printTitle(title)

-- ---------------------------------------------------------------------------
-- *** Globla Variables *** --
-- ---------------------------------------------------------------------------

High = true; Low = false

Output = true; Input = false

D0 = 0; D1 = 1; D2 = 2; D3 = 3; D4 = 4; D5 = 5; D6 = 6; D7 = 7; D8 = 8

OneHundredMilliSeconds   =  100; FiveHundredMilliSeconds  =   500
EighthSecond             =  125; QuarterSecond            =   250
HalfSecond               =  500; OneSecond                =  1000
TwoSeconds               = 2000; FourSeconds              =  4000
EightSeconds             = 8000; TenSeconds               = 10000

OneTime = 1; TwoTimes = 2; ThreeTimes = 3; FourTimes = 4; EightTimes = 8

-- ---------------------------------------------------------------------------
-- *** Debug Print Functions *** --
-- ---------------------------------------------------------------------------

function printTitle(title)
  local threeStars = '***'; local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'; local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- ---------------------------------------------------------------------------
-- *** GPIO Functions *** --
-- ---------------------------------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

function invertPinLevel(PinLevel)
  if pinLevel == High
    then
      pinLevel = Low
    else
      pinLevel = High
  end
end

-- ---------------------------------------------------------------------------
-- *** Static Timer Functions *** --
-- ---------------------------------------------------------------------------

function stopStaticTimer(timerNum)
  tmr.stop(timerNum)
end

function stopAllStaticTimers()
  for i = 0, 6, 1
    do
      stopStaticTimer(i)
  end
end

-- ---------------------------------------------------------------------------
-- *** Setup Functions *** --
-- ---------------------------------------------------------------------------

function setAllPinsOutput()
  for i = 0, 8, 1
    do
      setPinMode(i, Output)
  end
end

function setAllPinsLow()
  for i = 0, 8, 1
    do
      setPinLow(i)
  end
end

function setupPins()
  setAllPinsOutput()
  setAllPinsLow()
end

-- ---------------------------------------------------------------------------
-- *** Toggle pin functions *** --
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** togglePin07 - Toggle pin N times using highTimer and lowTimer *** --
-- ---------------------------------------------------------------------------

function togglePin07(pinNum, highTime, lowTime, toggleCount)

  -- Debug Print Statements ***
  printTitle('Begin togglePin07, ...')

  -- Callback Functions ***
  function highTimer07Callback()
    setPinLow(pinNum) 
    toggleCount = toggleCount - 1
    if toggleCount ~= 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
    end
  end

  function lowTimer07Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  highTimer = tmr.create()
  lowTimer  = tmr.create()

  -- *** Config Timers ***

  highTimer:register(highTime, tmr.ALARM_SEMI, highTimer07Callback)
  lowTimer:register (lowTime,  tmr.ALARM_SEMI, lowTimer07Callback)

  -- *** Action ***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  highTimer:start()
  
end

-- ---------------------------------------------------------------------------
-- *** togglePin08 - toggle pin n times with an additional delayTimer *** --
-- ---------------------------------------------------------------------------

function togglePin08(pinNum, delayTime, highTime, lowTime, count)

  -- Debug Print Statements ***
  printTitle('Begin togglePin08, ...')

  -- Callback Functions ***

  function delayTimer08Callback()
    setPinHigh(pinNum)
    highTimer:start()
  end
  
  function highTimer08Callback()
    setPinLow(pinNum) 
    count = count - 1
    if count ~= 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
    end
  end

  function lowTimer08Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  delayTimer = tmr.create()
  highTimer  = tmr.create()
  lowTimer   = tmr.create()

  -- *** Config Timers ***

  delayTimer:register(delayTime, tmr.ALARM_SINGLE, delayTimer08Callback)
  highTimer :register(highTime,  tmr.ALARM_SEMI,   highTimer08Callback)
  lowTimer  :register(lowTime,   tmr.ALARM_SEMI,   lowTimer08Callback)

  -- *** Action ***
  delayTimer:start()  
end

-- ---------------------------------------------------------------------------
-- *** togglePin09 - Toggle Pin additional delayTimer and scheduleTimer *** --
-- ---------------------------------------------------------------------------

function togglePin09(taskCount, taskDelayTime, pinNum, delayTime, highTime, lowTime, count)

  -- Debug Print Statements ***
  printTitle('Begin togglePin09, ...')

  -- Callback Functions ***

  function scheduleTimer09Callback()
    taskCount = taskCount - 1
    if taskCount >= 0 
      then
        delayTimer:start()
      else
        scheduleTimer:stop()
    end
  end

  function delayTimer09Callback()
    setPinHigh(pinNum)
    tempCount = count
    highTimer:start()
  end
  
  function highTimer09Callback()
    setPinLow(pinNum) 
    tempCount = tempCount - 1
    if tempCount > 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	lowTimer:stop()
	scheduleTimer:start()
    end
  end

  function lowTimer09Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  scheduleTimer = tmr.create()
  delayTimer    = tmr.create()
  highTimer     = tmr.create()
  lowTimer      = tmr.create()

  -- *** Config Timers ***
  scheduleTimer:register(taskDelayTime, tmr.ALARM_SEMI, scheduleTimer09Callback)
  delayTimer:register(delayTime, tmr.ALARM_SEMI, delayTimer09Callback)
  highTimer :register(highTime,  tmr.ALARM_SEMI,   highTimer09Callback)
  lowTimer  :register(lowTime,   tmr.ALARM_SEMI,   lowTimer09Callback)

  -- *** Action ***
  scheduleTimer:start()    
end

-- ---------------------------------------------------------------------------
-- *** togglePin10 - using argument PinTbl and BlinkTbl *** --
-- ---------------------------------------------------------------------------

pinTbl01   = {}
pinTbl01.taskCount     = FourTimes
pinTbl01.taskDelayTime = HalfSecond
pinTbl01.pinNum        = D4
pinTbl01.delayTime     = OneSecond
pinTbl01.highTime      = QuarterSecond
pinTbl01.lowTime       = QuarterSecond
pinTbl01.toggleCount   = TwoTimes  

function newbieBlink10(pinTbl)
  taskCount     = pinTbl.taskCount
  taskDelayTime = pinTbl.taskDelayTime
  pinNum        = pinTbl.pinNum 
  delayTime     = pinTbl.delayTime 
  highTime      = pinTbl.highTime 
  lowTime       = pinTbl.lowTime 
  toggleCount   = pinTbl.toggleCount
  togglePin09(taskCount, taskDelayTime, pinNum, delayTime, highTime, lowTime, count)
end

-- ---------------------------------------------------------------------------
-- *** Test Functions *** --
-- ---------------------------------------------------------------------------

--p4_d0_h250_l500_c8()  -- Pin4, Delay 0 seconds, Slow toggle, 8 times
function test_PinD4_DelayZero_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
  pinNum = D4; highTime = QuarterSecond; lowTime = HalfSecond; toggleCount = EightTimes;
  togglePin07(pinNum, highTime, lowTime, toggleCount)
end

function p4_d0_h250_l500_c8()
  test_PinD4_DelayZero_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
end

--p4_d4_h250_l500_c8()  -- Pin4, Delay 4 seconds, Slow toggle, 8 times
function test_PinD4_DelayFourSeconds_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
  pinNum = D4; delayTime = FourSeconds; highTime = QuarterSecond; lowTime = HalfSecond; count = EightTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
end

function p4_d4_h250_l500_c8()
  test_PinD4_DelayFourSeconds_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
end

--p4_d2_h250_l250_c2()  -- Pin4, Delay 2 seconds, Fast toggle, 2 times
function test_PinD4_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountTwoTimes()
  pinNum = D4; delayTime = TwoSeconds; highTime = QuarterSecond; lowTime = QuarterSecond; count = TwoTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
end

function p4_d2_h250_l250_c2()
  test_PinD4_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountTwoTimes()
end

--p0_d2_h250_l250_c4()  -- Pin0, Delay 2 seconds, Fast toggle, 4 times
function test_PinD0_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountFourTimes()
  pinNum = D0; delayTime = TwoSeconds; highTime = QuarterSecond; lowTime = QuarterSecond; count = FourTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
end

function p0_d2_h250_l250_c4()
  test_PinD0_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountFourTimes()
end

-- ---------------------------------------------------------------------------
-- *** Pin Tables *** --------------------------------------------------------
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** Main Function *** -----------------------------------------------------
-- ---------------------------------------------------------------------------

function main()

  -- *** Setup *** --
  setupPins()
  stopAllStaticTimers()

  --p4_d0_h250_l500_c8()  -- Pin4, Delay 0 seconds, Slow toggle, 8 times
  --p4_d4_h250_l500_c8()  -- Pin4, Delay 4 seconds, Slow toggle, 8 times
  --p4_d2_h250_l250_c2()  -- Pin4, Delay 2 seconds, Fast toggle, 2 times
  --p0_d2_h250_l250_c4()  -- Pin0, Delay 2 seconds, Fast toggle, 4 times

  --[[
  taskCount = FourTimes; taskDelayTime = HalfSecond
  pinNum = D4; delayTime = OneSecond; highTime = QuarterSecond; lowTime = QuarterSecond; count = TwoTimes;
  togglePin09(taskCount, taskDelayTime, pinNum, delayTime, highTime, lowTime, count)
  --]]

  --newbieBlink10(pinTbl01)

end

-- ---------------------------------------------------------------------------
-- *** Main *** --------------------------------------------------------------
-- ---------------------------------------------------------------------------

main()

end  

-- ---------------------------------------------------------------------------
-- *** End *** --
-- ---------------------------------------------------------------------------

Re: GPIO.input voltage levels vs edge detection

Posted: Thu Nov 08, 2018 4:06 am
by tlfong01
tlfong01 wrote:
Tue Nov 06, 2018 2:22 pm
Newbie Blink Selfie Walking Through Notes
NodeMCU Board Troubleshooting Power Reset Tip
Using table as function argument, according to open close principle
NewbieBlink Version 10 Using Pin Table Argument Working OK.

Testing NodeMCU board with big 100uF 6V3 tatalum capacitor

I still find the 8 Wemos NodeMCU boards have intermittent failures on running the NewbieBlink V10. I now suspect that the boards do not have stable performance because they do not have a good power supply.

I checked the AMS1117 low drop out voltage regulator IC and found its guaranteed drop out of 1.3V at 1A rated output at 5V is OK. The USB 5V power measured 4.6/4.8V at the board and static Vcc 3.25V looks good.

Anyway, I think it a good idea to test a board with a big cap, and also UART to TTL cable compatible can perhaps makes it easier to debug.

ESPlorer Log
...

Code: Select all

*** ESPlorer Log tlfong01 2018nov08hkt1358 ***

Logging enable
Load saved settings: Firmware:NodeMCU
Snippets: loading...
Snippets load: Success.
Set new color theme: Success.
Load saved settings: DONE.
Snippets: loading...
Snippets load: Success.
Scan system...
found last saved serial port COM30
Scan done.

---

PORT OPEN 115200

Communication with MCU..Got answer! Communication with MCU established.
AutoDetect firmware...

Can't autodetect firmware, because proper answer not received (may be unknown firmware). 
Please, reset module or continue.

add if0

_flash_used_end:40290000
fs.start:90000,max:36b000
_flash_used_end:40290000
fs.start:90000,max:36a000
_flash_used_end:40290000
fs.start:a0000,max:35b000
_flash_used_end:40290000
fs.start:a0000,max:35a000
mount res: 0, 0

Task task_lua started.

Flash sig not correct: 0 vs fafaaf50

nul mode, fpm auto sleep set:enalbe

NodeMCU custom build by frightanic.com
	branch: master
	commit: 3661b8d5eb5b42ed2d5ff51fa8e9628c17270973
	SSL: false
	modules: file,gpio,i2c,net,node,spi,tmr,uart,wifi

 build created on 2018-09-21 08:04

 powered by Lua 5.1.4 on SDK 2.2.1(6ab97e9)

lua: cannot open init.lua

> Heap size:43376.
scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 2
cnt 

connected with tlfong01, channel 2
dhcp client start...

 EVENT_DBG(wifi_event_monitor_handle_event_cb): was called (Event:0)
ip:192.168.1.4,mask:255.255.255.0,gw:192.168.1.1

 EVENT_DBG(wifi_event_monitor_handle_event_cb): was called (Event:3)

---

 EVENT_DBG(wifi_event_monitor_handle_event_cb): was called (Event:3)
pm open,type:2 0

Handle Input: first=1, pos=122, len=256, actual=122, line=r,u,t=file.fsinfo() print("Total : "..t.." bytes\r\nUsed  : "..u.." bytes\r\nRemain: "..r.." bytes\r\n") r=nil u=nil t=nil
total: 3322738, used:4769
Total : 3322738 bytes
Used  : 4769 bytes
Remain: 3317969 bytes

---

-- ---------------------------------------------------------------------------
-- *** Newbie Blinky Version 10 2018nov0701a tlfong01 2018nov *** --
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** Title *** --
-- ---------------------------------------------------------------------------

title = 'blinky2018nov0701a() tlfong01 2018nov07hkt1137'
printTitle(title)

-- ---------------------------------------------------------------------------
-- *** Globla Variables *** --
-- ---------------------------------------------------------------------------

High = true; Low = false

Output = true; Input = false

D0 = 0; D1 = 1; D2 = 2; D3 = 3; D4 = 4; D5 = 5; D6 = 6; D7 = 7; D8 = 8

OneHundredMilliSeconds   =  100; FiveHundredMilliSeconds  =   500
EighthSecond             =  125; QuarterSecond            =   250
HalfSecond               =  500; OneSecond                =  1000
TwoSeconds               = 2000; FourSeconds              =  4000
EightSeconds             = 8000; TenSeconds               = 10000

OneTime = 1; TwoTimes = 2; ThreeTimes = 3; FourTimes = 4; EightTimes = 8

-- ---------------------------------------------------------------------------
-- *** Debug Print Functions *** --
-- ---------------------------------------------------------------------------

function printTitle(title)
  local threeStars = '***'; local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'; local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- ---------------------------------------------------------------------------
-- *** GPIO Functions *** --
-- ---------------------------------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

function invertPinLevel(PinLevel)
  if pinLevel == High
    then
      pinLevel = Low
    else
      pinLevel = High
  end
end

-- ---------------------------------------------------------------------------
-- *** Static Timer Functions *** --
-- ---------------------------------------------------------------------------

function stopStaticTimer(timerNum)
  tmr.stop(timerNum)
end

function stopAllStaticTimers()
  for i = 0, 6, 1
    do
      stopStaticTimer(i)
  end
end

-- ---------------------------------------------------------------------------
-- *** Setup Functions *** --
-- ---------------------------------------------------------------------------

function setAllPinsOutput()
  for i = 0, 8, 1
    do
      setPinMode(i, Output)
  end
end

function setAllPinsLow()
  for i = 0, 8, 1
    do
      setPinLow(i)
  end
end

function setupPins()
  setAllPinsOutput()
  setAllPinsLow()
end

-- ---------------------------------------------------------------------------
-- *** Toggle pin functions *** --
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** togglePin07 - Toggle pin N times using highTimer and lowTimer *** --
-- ---------------------------------------------------------------------------

function togglePin07(pinNum, highTime, lowTime, toggleCount)

  -- Debug Print Statements ***
  printTitle('Begin togglePin07, ...')

  -- Callback Functions ***
  function highTimer07Callback()
    setPinLow(pinNum) 
    toggleCount = toggleCount - 1
    if toggleCount ~= 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
    end
  end

  function lowTimer07Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  highTimer = tmr.create()
  lowTimer  = tmr.create()

  -- *** Config Timers ***

  highTimer:register(highTime, tmr.ALARM_SEMI, highTimer07Callback)
  lowTimer:register (lowTime,  tmr.ALARM_SEMI, lowTimer07Callback)

  -- *** Action ***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  highTimer:start()
  
end

-- ---------------------------------------------------------------------------
-- *** togglePin08 - toggle pin n times with an additional delayTimer *** --
-- ---------------------------------------------------------------------------

function togglePin08(pinNum, delayTime, highTime, lowTime, count)

  -- Debug Print Statements ***
  printTitle('Begin togglePin08, ...')

  -- Callback Functions ***

  function delayTimer08Callback()
    setPinHigh(pinNum)
    highTimer:start()
  end
  
  function highTimer08Callback()
    setPinLow(pinNum) 
    count = count - 1
    if count ~= 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	highTimer:unregister()
	lowTimer:stop()
	lowTimer:unregister()
    end
  end

  function lowTimer08Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  delayTimer = tmr.create()
  highTimer  = tmr.create()
  lowTimer   = tmr.create()

  -- *** Config Timers ***

  delayTimer:register(delayTime, tmr.ALARM_SINGLE, delayTimer08Callback)
  highTimer :register(highTime,  tmr.ALARM_SEMI,   highTimer08Callback)
  lowTimer  :register(lowTime,   tmr.ALARM_SEMI,   lowTimer08Callback)

  -- *** Action ***
  delayTimer:start()  
end

-- ---------------------------------------------------------------------------
-- *** togglePin09 - Toggle Pin additional delayTimer and scheduleTimer *** --
-- ---------------------------------------------------------------------------

function togglePin09(taskCount, taskDelayTime, pinNum, delayTime, highTime, lowTime, count)

  -- Debug Print Statements ***
  printTitle('Begin togglePin09, ...')

  -- Callback Functions ***

  function scheduleTimer09Callback()
    taskCount = taskCount - 1
    if taskCount >= 0 
      then
        delayTimer:start()
      else
        scheduleTimer:stop()
    end
  end

  function delayTimer09Callback()
    setPinHigh(pinNum)
    tempCount = count
    highTimer:start()
  end
  
  function highTimer09Callback()
    setPinLow(pinNum) 
    tempCount = tempCount - 1
    if tempCount > 0
      then
        lowTimer:start()
      else
        highTimer:stop()
	lowTimer:stop()
	scheduleTimer:start()
    end
  end

  function lowTimer09Callback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  -- *** Create Timers ***
  scheduleTimer = tmr.create()
  delayTimer    = tmr.create()
  highTimer     = tmr.create()
  lowTimer      = tmr.create()

  -- *** Config Timers ***
  scheduleTimer:register(taskDelayTime, tmr.ALARM_SEMI, scheduleTimer09Callback)
  delayTimer:register(delayTime, tmr.ALARM_SEMI, delayTimer09Callback)
  highTimer :register(highTime,  tmr.ALARM_SEMI,   highTimer09Callback)
  lowTimer  :register(lowTime,   tmr.ALARM_SEMI,   lowTimer09Callback)

  -- *** Action ***
  scheduleTimer:start()    
end

-- ---------------------------------------------------------------------------
-- *** togglePin10 - using argument PinTbl and BlinkTbl *** --
-- ---------------------------------------------------------------------------

pinTbl01   = {}
pinTbl01.taskCount     = FourTimes
pinTbl01.taskDelayTime = HalfSecond
pinTbl01.pinNum        = D4
pinTbl01.delayTime     = OneSecond
pinTbl01.highTime      = QuarterSecond
pinTbl01.lowTime       = QuarterSecond
pinTbl01.toggleCount   = TwoTimes  

function newbieBlink10(pinTbl)
  taskCount     = pinTbl.taskCount
  taskDelayTime = pinTbl.taskDelayTime
  pinNum        = pinTbl.pinNum 
  delayTime     = pinTbl.delayTime 
  highTime      = pinTbl.highTime 
  lowTime       = pinTbl.lowTime 
  toggleCount   = pinTbl.toggleCount
  togglePin09(taskCount, taskDelayTime, pinNum, delayTime, highTime, lowTime, count)
end

-- ---------------------------------------------------------------------------
-- *** Test Functions *** --
-- ---------------------------------------------------------------------------

--p4_d0_h250_l500_c8()  -- Pin4, Delay 0 seconds, Slow toggle, 8 times
function test_PinD4_DelayZero_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
  pinNum = D4; highTime = QuarterSecond; lowTime = HalfSecond; toggleCount = EightTimes;
  togglePin07(pinNum, highTime, lowTime, toggleCount)
end

function p4_d0_h250_l500_c8()
  test_PinD4_DelayZero_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
end

--p4_d4_h250_l500_c8()  -- Pin4, Delay 4 seconds, Slow toggle, 8 times
function test_PinD4_DelayFourSeconds_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
  pinNum = D4; delayTime = FourSeconds; highTime = QuarterSecond; lowTime = HalfSecond; count = EightTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
end

function p4_d4_h250_l500_c8()
  test_PinD4_DelayFourSeconds_HighTimeQuarterSecond_LowTimeHalfSecond_CountEightTimes()
end

--p4_d2_h250_l250_c2()  -- Pin4, Delay 2 seconds, Fast toggle, 2 times
function test_PinD4_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountTwoTimes()
  pinNum = D4; delayTime = TwoSeconds; highTime = QuarterSecond; lowTime = QuarterSecond; count = TwoTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
end

function p4_d2_h250_l250_c2()
  test_PinD4_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountTwoTimes()
end

--p0_d2_h250_l250_c4()  -- Pin0, Delay 2 seconds, Fast toggle, 4 times
function test_PinD0_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountFourTimes()
  pinNum = D0; delayTime = TwoSeconds; highTime = QuarterSecond; lowTime = QuarterSecond; count = FourTimes;
  togglePin08(pinNum, delayTime, highTime, lowTime, count)
end

function p0_d2_h250_l250_c4()
  test_PinD0_DelayTwoSeconds_HighTimeQuarterSecond_LowTimeQuarterSecond_CountFourTimes()
end

-- ---------------------------------------------------------------------------
-- *** Pin Tables *** --------------------------------------------------------
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** Main Function *** -----------------------------------------------------
-- ---------------------------------------------------------------------------

function main()

  -- *** Setup *** --
  setupPins()
  stopAllStaticTimers()

  p4_d0_h250_l500_c8()  -- Pin4, Delay 0 seconds, Slow toggle, 8 times
  --p4_d4_h250_l500_c8()  -- Pin4, Delay 4 seconds, Slow toggle, 8 times
  --p4_d2_h250_l250_c2()  -- Pin4, Delay 2 seconds, Fast toggle, 2 times
  --p0_d2_h250_l250_c4()  -- Pin0, Delay 2 seconds, Fast toggle, 4 times

  --[[
  taskCount = FourTimes; taskDelayTime = HalfSecond
  pinNum = D4; delayTime = OneSecond; highTime = QuarterSecond; lowTime = QuarterSecond; count = TwoTimes;
  togglePin09(taskCount, taskDelayTime, pinNum, delayTime, highTime, lowTime, count)
  --]]

  --newbieBlink10(pinTbl01)

end

-- ---------------------------------------------------------------------------
-- *** Main *** --------------------------------------------------------------
-- ---------------------------------------------------------------------------

main()

end  

-- ---------------------------------------------------------------------------
-- *** End *** --
-- ---------------------------------------------------------------------------

rio de lua - nellie mckay 2,011 views
https://www.youtube.com/watch?v=bi9ZK1pX_gM

Nellie McKay - Wikipedia, the free encyclopedia

Nell Marie McKay (born 1982) is a British-American singer and songwriter. She made her Broadway debut in The Threepenny Opera (2006).

Early life and education

McKay was born in London to an English father, writer-director Malcolm McKay, and an American mother, actress Robin Pappas.

While growing up, she lived with her mother in Harlem, New York, in Olympia, Washington and in Mount Pocono, Pennsylvania. She studied jazz voice at the Manhattan School of Music, but did not graduate. Her performances at various New York City music venues, including the Sidewalk Cafe and Joe's Pub, drew attention from record labels. She signed with Columbia Records.

Career
...

Re: GPIO.input voltage levels vs edge detection

Posted: Thu Nov 08, 2018 7:35 am
by tlfong01
tlfong01 wrote:
Thu Nov 08, 2018 4:06 am
Newbie Blink Selfie Walking Through Notes
NodeMCU Board Troubleshooting Power Reset Tip
Using table as function argument, according to open close principle
NewbieBlink Version 10 Using Pin Table Argument Working OK.
Testing NodeMCU board with big 100uF 6V3 tatalum capacitor

NewbieBlink V11 Test Driven Development Notes

I am refactoring two old functions, using pinTable as the single argument. So far so good.

function testTogglePin1101() -- Toggle D4 high 250mS, low 250mS, 8 Times
pinNum = 4; highTime = 250; lowTime = 250; toggleCount = 8
togglePin1101(pinNum, highTime, lowTime, toggleCount)
end


function testTogglePin1102() -- Toggle D4 high 500mS, low 500mS, 2 times
-- *** Pin Table ** --
pinTable1102 = {}
pinTable1102.pinNum = D4
pinTable1102.highTime = HalfSecond
pinTable1102.lowTime = HalfSecond
pinTable1102.toggleCount = FourTimes
-- *** Action *** --
togglePin1102(pinTable1102)
end

Code: Select all

-- ---------------------------------------------------------------------------
-- *** Newbie Blinky Version 11 2018nov080 tlfong01 2018nov08hkt1410 *** --
-- ---------------------------------------------------------------------------

--[[
Change Notes:

2018nov08hkt1417:
1. Static timers any more, all the associated functions and varibles removed.
2. All old togglePin() removed.  
3. New versions start with V11.0

--]]

-- ---------------------------------------------------------------------------
-- *** Title *** --
-- ---------------------------------------------------------------------------

title = 'newbieBlinkyV1102f() tlfong01 2018nov08hkt1522'
printTitle(title)

-- ---------------------------------------------------------------------------
-- *** Globla Variables *** --
-- ---------------------------------------------------------------------------

High = true; Low = false

Output = true; Input = false

D0 = 0; D1 = 1; D2 = 2; D3 = 3; D4 = 4; D5 = 5; D6 = 6; D7 = 7; D8 = 8

OneHundredMilliSeconds   =  100; FiveHundredMilliSeconds  =   500
EighthSecond             =  125; QuarterSecond            =   250
HalfSecond               =  500; OneSecond                =  1000
TwoSeconds               = 2000; FourSeconds              =  4000
EightSeconds             = 8000; TenSeconds               = 10000

OneTime = 1; TwoTimes = 2; ThreeTimes = 3; FourTimes = 4; EightTimes = 8

-- ---------------------------------------------------------------------------
-- *** Debug Print Functions *** --
-- ---------------------------------------------------------------------------

function printTitle(title)
  local threeStars = '***'; local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'; local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- ---------------------------------------------------------------------------
-- *** GPIO Functions *** --
-- ---------------------------------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

function invertPinLevel(PinLevel)
  if pinLevel == High
    then
      pinLevel = Low
    else
      pinLevel = High
  end
end

-- ---------------------------------------------------------------------------
-- *** Setup Functions *** --
-- ---------------------------------------------------------------------------

function setAllPinsOutput()
  for i = 0, 8, 1
    do
      setPinMode(i, Output)
  end
end

function setAllPinsLow()
  for i = 0, 8, 1
    do
      setPinLow(i)
  end
end

function setupPins()
  setAllPinsOutput()
  setAllPinsLow()
end

-- ---------------------------------------------------------------------------
-- *** Toggle pin functions *** --
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** togglePin1101 - Toggle N times using highTimer and lowTimer *** --
-- ---------------------------------------------------------------------------

--[[
Function togglePin1101()
Description:
1. This function create two timers, highTimer11 and lowTimer11.

--]]

function togglePin1101(pinNum, highTime, lowTime, toggleCount)

  -- Debug Print Statements ***
  printTitle('Begin togglePin1101, ...')

  -- Callback Functions ***
  function highTimer11Callback()
    setPinLow(pinNum) 
    toggleCount = toggleCount - 1
    if toggleCount > 0
      then
        lowTimer11:start()
      else
        highTimer11:stop()
	highTimer11:unregister()
	lowTimer11:stop()
	lowTimer11:unregister()
    end
  end

  function lowTimer11Callback()
    setPinHigh(pinNum)  
    highTimer11:start()
  end

  -- *** Create Timers ***
  highTimer11 = tmr.create()
  lowTimer11  = tmr.create()

  -- *** Config Timers ***

  highTimer11:register(highTime, tmr.ALARM_SEMI, highTimer11Callback)
  lowTimer11:register (lowTime,  tmr.ALARM_SEMI, lowTimer11Callback)

  -- *** Action ***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  highTimer11:start()
  
end

function testTogglePin1101() -- Toggle D4 high 250mS, low 250mS, 8 Times
  pinNum = 4; highTime = 250; lowTime = 250; toggleCount = 8 
  togglePin1101(pinNum, highTime, lowTime, toggleCount)
end

-- ---------------------------------------------------------------------------
-- *** togglePin1102 - Toggle N times using highTimer and lowTimer *** --
-- ---------------------------------------------------------------------------

--[[
Function togglePin1102()
Description:
1. This function create two timers, highTimer11 and lowTimer11.
2. Same as 1101, but uses single argument pinTable1102
--]]

function togglePin1102(pinTable)
  printTitle('  Begin togglePin1102, ...')
  pinNum      = pinTable.pinNum
  highTime    = pinTable.highTime
  lowTime     = pinTable.lowTime
  toggleCount = pinTable.toggleCount

  togglePin1101(pinNum, highTime, lowTime, toggleCount)
end

function testTogglePin1102() -- Toggle D4 high 500mS, low 500mS, 2 times 

  -- *** Pin Table ** -- 
  pinTable1102               = {}
  pinTable1102.pinNum        = D4
  pinTable1102.highTime      = HalfSecond 
  pinTable1102.lowTime       = HalfSecond
  pinTable1102.toggleCount   = FourTimes    

  -- *** Action *** --
  togglePin1102(pinTable1102) 
end

-- ---------------------------------------------------------------------------
-- *** Main Function *** -----------------------------------------------------
-- ---------------------------------------------------------------------------

function main()

  -- *** Setup *** --
  printTitle(title)
  setupPins()

  --testTogglePin1101() -- Toggle D4 high 250mS, low 250mS, 8 Times
  testTogglePin1102() -- Toggle D4 high 500mS, low 500mS, 4 Times
end

-- ---------------------------------------------------------------------------
-- *** Main *** --------------------------------------------------------------
-- ---------------------------------------------------------------------------

main()

end  

-- ---------------------------------------------------------------------------
-- *** End *** --
-- ---------------------------------------------------------------------------

Re: GPIO.input voltage levels vs edge detection

Posted: Thu Nov 08, 2018 2:49 pm
by tlfong01
tlfong01 wrote:
Thu Nov 08, 2018 7:35 am
Newbie Blink Selfie Walking Through Notes
NodeMCU Board Troubleshooting Power Reset Tip
Using table as function argument, according to open close principle
NewbieBlink Version 10 Using Pin Table Argument Working OK.
Testing NodeMCU board with big 100uF 6V3 tatalum capacitor
NewbieBlink V11 Test Driven Development Notes
I am refactoring two old functions, using pinTable as the single argument.

NewbieBlink Version 11.03 tested OK

Now I have completed two functions to do the following:

1. noDelayToggle(slowToggleFourTimes)

2. delayToggle(longDelayFastToggleEightTimes)


This version is very newbie friendly (Mr Green's opinion) :mrgreen:

The program is MCV (Minimal, Complete, Verifiable), in the sense that a newbie can just download the code and run it. Everything, including kitchen sink, is included in the program, no nothing needs to be imported (required) .

The program has very few comments, because few are required: all variables and functions have meaningful names.

I have spent three hobbyist weeks to develop this newbie blink program. I think any Lua/NodeMCU newbie also needs at least two weeks to google and study, to fully understand the tricks and principles used in this program.

I still think Lua is very hard, not for ordinary people.

The newbieBlink V11.03 is about 300 lines long, and is fully listed below.

Appendix - Minimal, Complete, and Verifiable Example

(Minimal, Complete, and Verifiable example) RE: RELAY MODULE KY-019 5V Postby tlfong01 2018-Jul-22
viewtopic.php?f=37&t=77158&start=200#p1343828

How do I ask a good question? - Stack Overflow
https://stackoverflow.com/help/how-to-ask

How to create a Minimal, Complete, and Verifiable example - Stack Overflow
https://stackoverflow.com/help/mcve



Lua um tempão - 374,510 views
https://www.youtube.com/watch?v=mCcAocGKzOg
...
When will the moon be wine, I ask the blue sky;
I do not know the sky Palace, I ask what year.

...

Code: Select all

-- ---------------------------------------------------------------------------
-- *** Newbie Blinky Version 11.03u  tlfong01 2018nov08hkt2223 *** --
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** Title *** --
-- ---------------------------------------------------------------------------

title = 'newbieBlink1103u() tlfong01 2018nov08hkt2224'
printTitle(title)

-- ---------------------------------------------------------------------------
-- *** Globla Variables *** --
-- ---------------------------------------------------------------------------

High = true; Low = false
Output = true; Input = false
D0 = 0; D1 = 1; D2 = 2; D3 = 3; D4 = 4; D5 = 5; D6 = 6; D7 = 7; D8 = 8

OneHundredMilliSeconds   =  100; FiveHundredMilliSeconds  =   500
EighthSecond             =  125; QuarterSecond            =   250
HalfSecond               =  500; OneSecond                =  1000
TwoSeconds               = 2000; FourSeconds              =  4000
EightSeconds             = 8000; TenSeconds               = 10000

OneTime = 1; TwoTimes = 2; ThreeTimes = 3; FourTimes = 4; EightTimes = 8

-- ---------------------------------------------------------------------------
-- *** Debug Print Functions *** --
-- ---------------------------------------------------------------------------

function printTitle(title)
  local threeStars = '***'; local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'; local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- ---------------------------------------------------------------------------
-- *** GPIO Functions *** --
-- ---------------------------------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

function invertPinLevel(PinLevel)
  if pinLevel == High
    then
      pinLevel = Low
    else
      pinLevel = High
  end
end

-- ---------------------------------------------------------------------------
-- *** Setup Functions *** --
-- ---------------------------------------------------------------------------

function setAllPinsOutput()
  for i = 0, 8, 1
    do
      setPinMode(i, Output)
  end
end

function setAllPinsLow()
  for i = 0, 8, 1
    do
      setPinLow(i)
  end
end

function setupPins()
  setAllPinsOutput()
  setAllPinsLow()
end

-- ---------------------------------------------------------------------------
-- *** Toggle pin functions *** --
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** togglePin1102 - Toggle pin N times *** --
-- ---------------------------------------------------------------------------

-- Function togglePin1102() --

function togglePin1102(pinTable)
  printTitle('  Begin togglePin1102, ...')
  pinNum      = pinTable.pinNum
  highTime    = pinTable.highTime
  lowTime     = pinTable.lowTime
  toggleCount = pinTable.toggleCount

  -- Debug Print Statements ***
  printTitle('Begin togglePin1102, ...')

  -- Callback Functions ***
  function highTimer1102Callback()
    setPinLow(pinNum) 
    toggleCount = toggleCount - 1
    if toggleCount > 0
      then
        lowTimer1102:start()
      else
        highTimer1102:stop()
	highTimer1102:unregister()
	lowTimer1102:stop()
	lowTimer1102:unregister()
    end
  end

  function lowTimer1102Callback()
    setPinHigh(pinNum)  
    highTimer1102:start()
  end

  -- *** Create Timers ***
  highTimer1102 = tmr.create()
  lowTimer1102  = tmr.create()

  -- *** Config Timers ***

  highTimer1102:register(highTime, tmr.ALARM_SEMI, highTimer1102Callback)
  lowTimer1102:register (lowTime,  tmr.ALARM_SEMI, lowTimer1102Callback)

  -- *** Action ***
  setPinMode(pinNum, Output)
  setPinHigh(pinNum) 
  highTimer1102:start()

end

-- Function testTogglePin1102 --

function testTogglePin1102() -- Toggle D4 high 500mS, low 500mS, 2 times 

  -- *** Action *** --
  togglePin1102(pinTable1102) 
end

-- ---------------------------------------------------------------------------
-- *** togglePin1103 - Toggle pin N times *** --
-- ---------------------------------------------------------------------------

-- Function togglePin1103() --

function togglePin1103(pinTable)

  -- Callback Functions ***
  function highTimer1103Callback()
    setPinLow(pinNum) 
    toggleCount = toggleCount - 1
    if toggleCount > 0
      then
        lowTimer1103:start()
      else
        highTimer1103:stop()
	highTimer1103:unregister()
	lowTimer1103:stop()
	lowTimer1103:unregister()
    end
  end

  function lowTimer1103Callback()
    setPinHigh(pinNum)  
    highTimer1103:start()
  end

  function delayTimer1103Callback()
    setPinHigh(pinNum)
    highTimer1103:start()
  end

  -- Get arguments --

  pinNum      = pinTable.pinNum
  highTime    = pinTable.highTime
  lowTime     = pinTable.lowTime
  toggleCount = pinTable.toggleCount
  delayTime   = pinTable.delayTime

  -- Create Timers --

  highTimer1103   = tmr.create()
  lowTimer1103    = tmr.create()
  delayTimer1103  = tmr.create()

  -- Config Timers 

  highTimer1103:register(highTime, tmr.ALARM_SEMI, highTimer1103Callback)
  lowTimer1103:register (lowTime,  tmr.ALARM_SEMI, lowTimer1103Callback)
  delayTimer1103:register(delayTime, tmr.ALARM_SEMI, delayTimer1103Callback)

  -- *** Action ***
  printTitle('Begin togglePin1103, ...')
  --highTimer1103:start()
  delayTimer1103:start()

end

-- Function testTogglePin1103 --

function testTogglePin1103() 
  togglePin1103(pinTable1103) 
end

-- *** Pin Tables *** --

-- Pin Table pinTable1102 -- 

pinTable1102 = {}
  pinTable1102.pinNum        = D4
  pinTable1102.highTime      = HalfSecond 
  pinTable1102.lowTime       = HalfSecond
  pinTable1102.toggleCount   = FourTimes 

-- Pin Table pinTable1103 -- 

pinTable1103 = {}
  pinTable1103.pinNum        = D4
  pinTable1103.highTime      = OneHundredMilliSeconds 
  pinTable1103.lowTime       = OneHundredMilliSeconds 
  pinTable1103.toggleCount   = EightTimes 
  pinTable1103.delayTime     = FourSeconds

-- *** Aliases *** --

noDelayToggle       = togglePin1102
slowToggleFourTimes = pinTable1102

delayToggle         = togglePin1103
longDelayFastToggleEightTimes = pinTable1103 

-- ---------------------------------------------------------------------------
-- *** Main Function *** -----------------------------------------------------
-- ---------------------------------------------------------------------------

function main()

  printTitle(title)
  setupPins()

  noDelayToggle(slowToggleFourTimes)         --togglePin1102(pinTable1102) 
  --delayToggle(longDelayFastToggleEightTimes) --togglePin1103(pinTable1103) 

end

-- ---------------------------------------------------------------------------
-- *** Main *** --------------------------------------------------------------
-- ---------------------------------------------------------------------------

main()

end  

-- ---------------------------------------------------------------------------
-- *** End *** --
-- ---------------------------------------------------------------------------

Re: GPIO.input voltage levels vs edge detection

Posted: Sun Nov 11, 2018 4:08 am
by tlfong01
tlfong01 wrote:
Thu Nov 08, 2018 2:49 pm
NewbieBlink V11 Test Driven Development Notes
NewbieBlink Version 11.03 tested OK
The program is MCV (Minimal, Complete, Verifiable), in the sense that a newbie can just download the code and run it. Everything, including kitchen sink, is included in the program, no nothing needs to be imported.
The program has very few comments, because few are required: all variables and functions have meaningful names.
I have spent three hobbyist weeks to develop this newbie blink program. I think any Lua/NodeMCU newbie also needs at least two weeks to google and study, to fully understand the tricks and principles used in this program.

newbieBlink 12.15.13 Tested OK

I have cleaned up things and fully debugged version 12.15.13. The function

togglePin(pinTable01)

does the following things:

1. From pinTable01, input the following arguments:

1.1 Delay before start doing a number of toggle tasks.
1.2 Each toggle task consists of a number of set GPIO pin high and low.
1.3 The arguments are listed below:
1.3.1 pinNum = Pin number (D4 pin is the default connected to built in LED)
1.3.2 taskCount = number of tasks to do
1.3.3 delayTime = delay before starting the toggle tasks
1.3.4 toggleCount = number of GPIO pin set high/low toggles
1.3.5 highTime = time in milliSeconds of pin set high (built in LED off)
1.3.6 lowTime = time in milliSeconds of GPIO pin set low (built LED on)


Notes:
1. Three interrupt (no busy looping) timers are used: taskTimer, highTimer, lowTimer.
2. All GPIO pin setting high/low are interrupt timer (expired) event driven.


The program seems stable (Mr Green's conclusion) :mrgreen:
The program ran smoothly with the following boards the first time after power on and hardware reset (shorting reset pin and ground pin) .

WeMos D1Mini x 4
Amica x 4
No Brand NodeMCU V3 x 1



...

/ to continue, ... Next step is to add a schedule timer to toggle/blink all the pins/LEDs on Wemos D1 Mini.

...

Code: Select all

-- ---------------------------------------------------------------------------
-- *** newbieblink 12.15.13  last update 2018nov11hkt1124 *** --
-- ---------------------------------------------------------------------------

-- ---------------------------------------------------------------------------
-- *** Title - last update 2018nov11hkt1124 *** --
-- ---------------------------------------------------------------------------

title = 'newbieBlink v12.15.13'
printTitle(title)

-- ---------------------------------------------------------------------------
-- *** Globla Variables - last update 2018nov11hkt1124 *** --
-- ---------------------------------------------------------------------------

High = true; Low = false

Output = true; Input = false

D0 = 0; D1 = 1; D2 = 2; D3 = 3; D4 = 4; D5 = 5; D6 = 6; D7 = 7; D8 = 8

TenthSecond              =  100; OneHundredMilliSeconds   =   100; 
EighthSecond             =  125; QuarterSecond            =   250
HalfSecond               =  500; OneSecond                =  1000
TwoSeconds               = 2000; FourSeconds              =  4000
EightSeconds             = 8000; TenSeconds               = 10000

OneTime   = 1; TwoTimes = 2; ThreeTimes = 3; FourTimes  = 4; 
FiveTimes = 5; SixTimes = 6; SevenTimes = 7; EightTimes = 8

-- ---------------------------------------------------------------------------
-- *** Debug Print Functions - last update 2018nov11hkt1118 *** --
-- ---------------------------------------------------------------------------

function printTitle(title)
  local threeStars = '***'; local twoNewLines = '\n\n'
  print(twoNewLines, threeStars, title, threeStars)
end

function printTitleNum(title, num)
  local twoNewLines = '\n\n'; local fiveSpaces = '     '
  print(fiveSpaces, title, num)
end

-- ---------------------------------------------------------------------------
-- *** GPIO Functions - last update 2018nov11hkt1118 *** --
-- ---------------------------------------------------------------------------

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

function setPinLevel(pinNum, pinLevel)
  if pinLevel == High
    then
      setPinHigh(pinNum)
    else
      setPinLow(pinNum)
  end
end

-- ---------------------------------------------------------------------------
-- *** Setup Functions - last update 2018nov11hkt1119 *** --
-- ---------------------------------------------------------------------------

function setAllPinsOutput()
  for i = 0, 8, 1
    do
      setPinMode(i, Output)
  end
end

function setAllPinsLow()
  for i = 0, 8, 1
    do
      setPinLow(i)
  end
end

function setupPins()
  setAllPinsOutput()
  setAllPinsLow()
end

-- ---------------------------------------------------------------------------
-- *** togglePin - last update 2018nov11hkt1123 *** --
-- ---------------------------------------------------------------------------

function togglePin(pinTable)

  -- Get arguments from pinTable --

  pinNum		= pinTable.pinNum
  highTime		= pinTable.highTime
  lowTime		= pinTable.lowTime
  toggleCount		= pinTable.toggleCount
  toggleDelayTime	= pinTable.toggleDelayTime
  taskCount		= pinTable.taskCount

  -- Debug print statements --

  printTitle   ('function        = togglePin')
  printTitleNum('pinNum          =', taskDelayTime)
  printTitleNum('highTime        =', highTime)
  printTitleNum('lowTime         =', lowTime)
  printTitleNum('toggleCount     =', toggleCount)
  printTitleNum('toggleDelayTime =', toggleDelayTime)
  printTitleNum('taskCount       =', taskCount)

  -- Create Timers --

  highTimer = tmr.create()
  lowTimer	= tmr.create()
  taskTimer	= tmr.create()

  -- Callback Functions --

  function highTimerCallback()
    setPinLow(pinNum) 
    currentToggleCount = currentToggleCount - 1
    if currentToggleCount > 0
      then
        lowTimer:start()
      else
	taskTimer:start()
    end
  end

  function lowTimerCallback()
    setPinHigh(pinNum)  
    highTimer:start()
  end

  function taskTimerCallback()
    taskCount = taskCount - 1
    printTitleNum('taskCount =', taskCount)
      if taskCount >= 0
        then
          currentToggleCount = toggleCount
          setPinHigh(pinNum)
          highTimer:start()
        else
	  printTitle('End of all toggle tasks.')
	  highTimer:stop()
	  lowTimer:stop()
	  taskTimer:stop()
      end 
  end

  -- Config Timers --

  highTimer:register(highTime,        tmr.ALARM_SEMI, highTimerCallback)
  lowTimer:register (lowTime,         tmr.ALARM_SEMI, lowTimerCallback)
  taskTimer:register(toggleDelayTime, tmr.ALARM_SEMI, taskTimerCallback)

  -- Action --

  taskTimer:start()

end

-- Sample test data and tests --

-- Pin Table pinTable -- 

pinTable01 = 
  {
    pinNum          = D4,
    highTime        = TenthSecond, 
    lowTime         = TenthSecond, 
    toggleCount     = TwoTimes, 
    toggleDelayTime = TwoSeconds,
    taskCount       = FourTimes
  }

-- togglePin(pinTable)

-- End togglePin() ------------------------------------------------------- 

-- ---------------------------------------------------------------------------
-- *** Main Function *** -----------------------------------------------------
-- ---------------------------------------------------------------------------

function main()
  printTitle(title)
  setupPins()
  togglePin(pinTable01)
end

-- ---------------------------------------------------------------------------
-- *** Action *** --------------------------------------------------------------
-- ---------------------------------------------------------------------------

main()  

-- ---------------------------------------------------------------------------
-- *** End *** --
-- ---------------------------------------------------------------------------

Re: GPIO.input voltage levels vs edge detection

Posted: Sun Nov 11, 2018 6:11 am
by tlfong01
tlfong01 wrote:
Sun Nov 11, 2018 4:08 am
NewbieBlink V11 Test Driven Development Notes
NewbieBlink Version 11.03 tested OK
The program is MCV (Minimal, Complete, Verifiable), in the sense that a newbie can just download the code and run it. Everything, including kitchen sink, is included in the program, no nothing needs to be imported.
The program has very few comments, because few are required: all variables and functions have meaningful names.
I have spent three hobbyist weeks to develop this newbie blink program. I think any Lua/NodeMCU newbie also needs at least two weeks to google and study, to fully understand the tricks and principles used in this program.
newbieBlink 12.15.13 Tested OK

Testing NewbieBlink V121513 on NodeMCU V0.9.5 2018sep21 Firmware

To check out how stable V12.15.13, I repeatedly tested 4 old boards flashed with the very first built I did on 2018sep21, NodeMCU V0.9.5.

I found all old boards with old firmware ran the newbieBlink program without any problem.

Errata 2018nov11hkt1406

I jumped to the quick conclusion that earlier I wrongly accused my boards were fake boards using production reject grade chips.

I now think that all the 15+ boards I got from two reputable and two not so reputable TaoBao shops are good, except one which was dead on arrival.

Re: GPIO.input voltage levels vs edge detection

Posted: Tue Nov 13, 2018 4:52 am
by tlfong01
tlfong01 wrote:
Sun Nov 11, 2018 6:11 am
Testing NewbieBlink V121513 on NodeMCU V0.9.5 2018sep21 Firmware
To check out how stable V12.15.13, I repeatedly tested 4 old boards flashed with the very first built I did on 2018sep21, NodeMCU V0.9.5.
I found all old boards with old firmware ran the newbieBlink program without any problem.

NodeMCU / ESPlorer instability problem again! :(

However, as I am trying to add a little bit more code to the stable version, I again found problems. So I goggled to update myself.

ESP8266 by Angus Gratton - 2016feb12
https://www.youtube.com/watch?v=AMMOrwqSPwY

In this video, recorded live at linux.conf.au2016 in Geelong, Angus Gratton explains his (and others) efforts in reverse engineering the ESP8266 module using Free and Open Source tools. His talk covers a brief history of the device, how it came to be and his own anecdotal views on where its all going. With the impending arrival of the ESP32, the ability to upload from the Arduino IDE, the arrival of several open source based frameworks to develop with, the future of the Espressif device is bright.

4 reasons I abandoned NodeMCU/Lua for ESP8266 - InternetOfHomeThings 2015apr24 128,346 views 53 Responses
https://internetofhomethings.com/homethings/?p=424

InternetOfHomeThings - 2015apr24
I have concluded that the NodeMCU/Lua development environment is not suitable for ESP8266 application development.

GuyBlom - 2015nov19
As a veteran programmer of 25+ yrs I am loathe to waste time working around inherent instability issues and have quickly moved to seeking better alternatives.

Pete Cranwell - 2017dec31
I can't get my apps to run reliably. Switched to Arduino. It's rock solid for me. I've been working on computers since 1963. I've seen and worked with most languages and systems in that time. NodeMCU doesn't cut it for me.

Jerry Kaidor - 2018may29
I think I have gotten over being seduced by the supposed ease and simplicity of lua, have nailed enough jelly to the wall, ...

Marcel Stör - 2018may30
I'm one of the independent maintainers of the NodeMCU firmware.
It's unfortunate that you had bad experiences with "NodeMCU". However, as others in this thread, I feel you're lumping a few things together that should be addressed separately, ...

Re: GPIO.input voltage levels vs edge detection

Posted: Tue Nov 13, 2018 7:49 am
by tlfong01
tlfong01 wrote:
Tue Nov 13, 2018 4:52 am
NodeMCU / ESPlorer instability problem again!
However, as I am trying to add a little bit more code to the stable version, I again found problems. So I goggled to update myself.
4 reasons I abandoned NodeMCU/Lua for ESP8266 - InternetOfHomeThings 2015apr24 128,346 views 53 Responses
https://internetofhomethings.com/homethings/?p=424
InternetOfHomeThings - 2015apr24
I have concluded that the NodeMCU/Lua development environment is not suitable for ESP8266 application development.
GuyBlom - 2015nov19
As a veteran programmer of 25+ yrs I am loathe to waste time working around inherent instability issues and have quickly moved to seeking better alternatives.
Pete Cranwell - 2017dec31
I can't get my apps to run reliably. Switched to Arduino. It's rock solid for me. I've been working on computers since 1963. I've seen and worked with most languages and systems in that time. NodeMCU doesn't cut it for me.
Jerry Kaidor - 2018may29
I think I have gotten over being seduced by the supposed ease and simplicity of lua, have nailed enough jelly to the wall, ...

ESPlorer sometimes mysteriously executes old version or part of old version of a program, even when new version is uploaded and executed! :evil:

Earlier I concluded that ESP8266/NodeMCU/ESPlorer/Lua is not for ordinary people. I googled that even some experienced programmers found their ESP hardware/firmware not stable and gave up.

I might sooner of later give up because the instability problem.

One other thing is that the ESPLorer IDE is itself buggy. One very weird thing I just discovered is that ESPLorer sometimes executes an old version or part of an old version of a program even if a new version is uploaded!

It is not that the new version is not successfully uploaded, but the IDE seems becomes crazy and mess up things.

Errata 2018nov13hkt2204

I wrong thought that ESPlorer might get crazy and mixed up different versions of a program. Just now I quickly read the Lua programming book chapters on closures and lexical scoping and then realized that it is the newbie (ie, me) who is ignorant about about things like local and global functions (timer callback functions) that causes all the confusion.

So I think I need to spend at least 3 hours reading the relevant language book chapters before I have enough knowledge to debug the newbieBlink program which I have spent more than one hobbyist month and still have not completed!


ESP8266 and Stability of NodeMCU Firmware - 2016jan07
https://christoph-jahn.com/?p=1657

For someone like me who comes from a non-embedded background, ... the ideas of the NodeMCU firmware are really appealing. A nice scripting language, a slick GUI for rapid prototyping ESPlorer together with a highly active community seemed a perfect fit.

Unfortunately it did not work for me. The whole setup was unstable and I spent many hours to get a prototype (WiFi and MQTT connection) working reliably.

I failed miserably with erratic behavior of the system.

Sometimes a code change was “detected”,

sometimes the old code was still executed.

Compiling helped often but not always.

There are others who made the same experience and obviously spent more time on trying as well as the write-up (e.g. this link). I will now experiment with the Arduino IDE extension.

I feel happy for all those people who use NodeMCU without issues and hope to rejoin them as soon as possible!

Re: GPIO.input voltage levels vs edge detection

Posted: Wed Nov 14, 2018 7:15 am
by tlfong01
tlfong01 wrote:
Tue Nov 13, 2018 7:49 am
NodeMCU / ESPlorer instability problem again!
However, as I am trying to add a little bit more code to the stable version, I again found problems.
ESPlorer sometimes mysteriously executes old version or part of old version of a program, even when new version is uploaded and executed!
Errata 2018nov13hkt2204
I wrong thought that ESPlorer might get crazy and mixed up different versions of a program. Just now I quickly read the Lua programming book chapters on closures and lexical scoping and then realized that it is me who is ignorant about about things like local and global functions (timer callback functions) that causes all the confusion.
So I think I need to spend at least 3 hours reading the relevant language book chapters before I have enough knowledge to debug the newbieBlink program which I have spent more than one hobbyist month and still have not completed!

NodeMCU Lua Newbie Debugging Tips

I goggled and skimmed through some good references and found the reasons why my newbieBlink program is unstable and often cause panic reboot of the ESP8366SDK/NodeMCU runtime.

Two important things I have been ignorant are the following:

1. How to declare local and global values.

I don't know that by default any variable that is referenced and not previously declared as local is global and this variable will persist in the global table until it is explicitly deleted. I guess this is why I thought ESPlorer executes old code. Actually some my timer callback functions of old and new version get messed up and cause wierd things happening.

2. How to delete global values no longer necessary.

There are also other important things I need to know in using ESP8266, together with Rpi, in IoT applications, as summarised in the appendices below.


Appendices - Lua Language and NodeMCU firmware References

Lua References

Programming in Lua 5.1 Free Online
https://www.lua.org/pil/contents.html

Programming in Lua 5.3 £22
https://store.feistyduck.com/products/p ... tion-ebook

Lua 5.1 Reference Manual
http://www.lua.org/manual/5.1/manual.html

Lua FAQ
http://www.lua.org/faq.html

Lua Users Wiki
http://lua-users.org/wiki/

NodeMCU Lau References

NodeMCU Lua Developer FAQ
https://nodemcu.readthedocs.io/en/maste ... loper-faq/

How is NodeMCU Lua different to standard Lua?
https://nodemcu.readthedocs.io/en/maste ... andard-lua

Lua itself is primarily an extension language that makes no assumptions about a "main" program:

Lua works embedded in a host application to provide a powerful, lightweight scripting language for use within the application. This host application can then invoke functions to execute a piece of Lua code, can write and read Lua variables, and can register C functions to be called by Lua code.

The NodeMCU Lua firmware is an ESP8266 application and must therefore be layered over the ESP8266 SDK. The firmware has replaced some standard Lua modules that don't align well with the SDK structure with ESP8266-specific versions. For example, the standard io and os libraries don't work, but have been largely replaced by the NodeMCU node and file libraries. The debug and math libraries have also been omitted to reduce the runtime footprint, ...

NodeMCU Lua is based on eLua, a fully featured implementation of Lua 5.1 that has been optimized for embedded system development and execution to provide a scripting framework that can be used to deliver useful applications within the limited RAM and Flash memory resources of embedded processors such as the ESP8266.

SDK is non-preemptive and event driven. Tasks can be associated with given events by using the SDK API to registering callback functions to the corresponding events. Events are queued internally within the SDK, and it then calls the associated tasks one at a time, with each task returning control to the SDK on completion. The SDK states that if any tasks run for more than 15 mSec, then services such as WiFi can fail.

The NodeMCU libraries act as C wrappers around registered Lua callback functions to enable these to be used as SDK tasks. You must therefore use an Event-driven programming style in writing your ESP8266 Lua programs. Most programmers are used to writing in a procedural style where there is a clear single flow of execution, and the program interfaces to operating system services by a set of synchronous API calls to do network I/O, etc. Whilst the logic of each individual task is procedural, this is not how you code up ESP8266 applications.

ESP8266 Specifics
https://nodemcu.readthedocs.io/en/maste ... -specifics

This is a fully featured Lua 5.1 implementation so all standard Lua language constructs and data types work.
The main standard Lua libraries: core, coroutine, string and table are implemented.

The ESP8266 uses a combination of on-chip RAM and off-chip Flash memory, ... Code can be executed directly from Flash, ...
both the RAM and the Flash memory are very limited when compared to systems that most application programmers use.

RAM available to developers, 15Kb with Version 0.9 builds to 45Kb with Version 2.x builds.

Early ESP8266 modules with 512Kb Flash, current NodeMCU firmware will fit comfortably in a 1Mb Flash and still have ample remaining Flash memory to support Lua IoT applications.

NodeMCU firmware makes any unused Flash memory available as a SPI Flash File System (SPIFFS) through the file library. How much Flash is available as SPIFFS file space depends on the number of modules included in the specific firmware build.

The developers that don't want to bother with setting up their own build environment can use Marcel Stör's excellent Cloud build service instead. ... general recommendation is to use floating point builds.

Unlike Arduino or ESP8266 development, where each application change requires the flashing of a new copy of the firmware, in the case of Lua the firmware is normally flashed once, and all application development is done by updating files on the SPIFFS file system. In this respect, Lua development on the ESP8266 is far more like developing applications on a more traditional PC. The firmware will only be reflashed if the developer wants to add or update one or more of the hardware-related libraries.

The ESP8266 runs the SDK over the native hardware, so there is no underlying operating system to capture errors and to provide graceful failure modes. Hence system or application errors can easily "PANIC" the system causing it to reboot. Error handling has been kept simple to save on the limited code space, and this exacerbates this tendency. Running out of a system resource such as RAM will invariably cause a messy failure and system reboot.

Espressif has a new RTOS alternative to the non-OS SDK, and the latest version SDK using RTOS.

There is currently no debug library support. So you have to use 1980s-style "binary-chop" to locate errors and use print statement diagnostics though the system's UART interface.

The runtime system runs in interactive-mode. In this mode it first executes any init.lua script. It then "listens" to the serial port for input Lua chunks, and executes them once syntactically complete.

There is no batch support, although automated embedded processing is normally achieved by setting up the necessary event triggers in the init.lua script.

The various libraries (net, tmr, wifi, etc.) use the SDK callback mechanism to bind Lua processing to individual events (for example a timer alarm firing). Developers should make full use of these events to keep Lua execution sequences short.

Stacking up such requests in a single Lua task function burns scarce RAM and can trigger a PANIC. This is true for timer, network, and other callbacks.

You, therefore, have to implement ESP8266 Lua applications using an event driven approach. You have to understand which SDK API requests schedule asynchronous processing, and which define event actions through Lua callbacks. Yes, such an event-driven approach makes it difficult to develop procedurally structured applications, but it is well suited to developing the sorts of application that you will typically want to implement on an IoT device.

So how does the SDK event / tasking system work in Lua?
https://nodemcu.readthedocs.io/en/maste ... ork-in-lua

So what Lua library functions enable the registration of Lua callbacks?
https://nodemcu.readthedocs.io/en/maste ... ork-in-lua

So what are the different ways of declaring variables and how is NodeMCU different here?
https://nodemcu.readthedocs.io/en/maste ... erent-here

Understanding how to delcare variables is of particular importance in the NodeMCU environment.

All variables in Lua can be classed as globals, locals or upvalues. But by default any variable that is referenced and not previously declared as local is global and this variable will persist in the global table until it is explicitly deleted. If you want to see what global variables are in scope then try

for k,v in pairs(_G) do print(k,v) end

Local variables are 'lexically scoped', and you may declare any variables as local within nested blocks or functions without affecting the enclosing scope. Because locals are lexically scoped you can also refer to local variables in an outer scope and these are still accessible within the inner scope. Such variables are know as upvalues.

Lua variable can be assigned two broad types of data: values such as numbers, booleans, and strings and references such as functions, tables and userdata. You can see the difference here when you assign the contents of a variable a to b. In the case of a value then it is simply copied into b. In the case of a reference, both a and b now refer to the same object, and no copying of content takes place. This process of referencing can have some counter-intuitive consequences. For example, in the following code by the time it exists, the variable tmr2func is out of scope. However a reference to the function has now been stored in the Lua registry by the alarm API call, so it and any upvalues that it uses will persist until it is eventually entirely dereferenced (e.g. by tmr2:unregister()).

You need to understand the difference between when a function is compiled, when it is bound as a closure and when it is invoked at runtime. The closure is normally bound once pretty much immediately after compile, but this isn't necessarily the case.

each closure inherits its own copies of the upvalues it uses so the regAddr for this function is 0x00). The upvalue list is created when the closure is created and even if the outer routine that initially declared them is no longer in scope ... the Lua RTS ensures that any upvalue will still persist whilst the closure persists.

On the other hand the storage for any locals is allocated each time the routine is called, and this can be many times in a running application.

Using locals and upvalues this way is both a lot faster at runtime and generates less bytecode instructions for their access.

So how is context passed between Lua event tasks?
https://nodemcu.readthedocs.io/en/maste ... vent-tasks

It is important to understand that a single Lua function is associated with / bound to any event callback task. Each function can invoke other functions and so on, but it must ultimately return control to the C library code which then returns control the SDK, terminating the task.

By their very nature Lua local variables only exist within the context of an executing Lua function, and so locals are unreferenced on exit and any local data (unless also a reference type such as a function, table, or user data which is also referenced elsewhere) can therefore be garbage collected between these lua_call() actions.

So context can only be passed between event routines by one of the following mechanisms:

Globals are by nature globally accessible. Any global will persist until explicitly dereferenced by assigning nil to it.

The File system is a special case of persistent global, so there is no reason in principle why it and the files it contains can't be used to pass context. However the ESP8266 file system uses flash memory and even with the SPIFFS file system still has a limited write cycle lifetime, so it is best to avoid using the file system to store frequently changing content except as a mechanism of last resort.

The Lua Registry. This is a normally hidden table used by the library modules to store callback functions and other Lua data types. The GC treats the registry as in scope and hence any content referenced in the registry will not be garbage collected.

Upvalues. These are a standard feature of Lua as described above that is fully implemented in NodeMCU. When a function is declared within an outer function, all of the local variables within the outer scope are available to the inner function.

Techniques for Reducing RAM and SPIFFS footprint - How do I minimise the footprint of an application?
https://nodemcu.readthedocs.io/en/maste ... vent-tasks

Perhaps the simplest aspect of reducing the footprint of an application is to get its scope correct. The ESP8266 is an IoT device and not a general purpose system. It is typically used to attach real-world monitors, controls, etc. to an intranet and is therefore designed to implement functions that have limited scope. We commonly come across developers who are trying to treat the ESP8266 as a general purpose device and can't understand why their application can't run.

The simplest and safest way to use IoT devices is to control them through a dedicated general purpose system on the same network. This could be a low cost system such as a RaspberryPi, running custom code or an open source home automation (HA) application. Such systems have orders of magnitude more capacity than the ESP8266, for example the RPi has 2GB RAM and its SD card can be up to 32GB in capacity, and it can support the full range of USB-attached disk drives and other devices. It also runs a fully featured Linux OS, and has a rich selection of applications pre configured for it.

Using a tiered approach where all user access to the ESP8266 is passed through a controlling server means that the end-user interface (or smartphone connector), together with all of the associated validation and security can be implemented on a system designed to have the capacity to do this. This means that you can limit the scope of your ESP8266 application to a limited set of functions being sent to or responding to requests from this system.

If you are trying to implement a user-interface or HTTP webserver in your ESP8266 then you are really abusing its intended purpose. When it comes to scoping your ESP8266 applications, the adage Keep It Simple Stupid truly applies.

How do I minimise the footprint of an application on the file system
https://nodemcu.readthedocs.io/en/maste ... ile-system

Once the code is tested and stable, then compress it using LuaSrcDiet before downloading to the ESP8266. Doing this will reduce the code footprint on the SPIFFS by 2-3x. Also note that LuaSrcDiet has a mode which achieves perhaps 95% of the possible code compaction but which still preserves line numbering. This means that any line number-based error messages will still be usable.

How do I minimise the footprint of running application?
https://nodemcu.readthedocs.io/en/maste ... pplication

Setting any variable to nil dereferences the previous context of that variable. This approach ensures that the module can be fully dereferenced on completion.

Lua execution is intrinsically divided into separate event tasks with each bound to a Lua callback. This, when coupled with the strong dispose on dereference feature, means that it is very easy to structure your application using an classic technique which dates back to the 1950s known as Overlays.

How do I reduce the size of my compiled code?
https://nodemcu.readthedocs.io/en/maste ... piled-code

How do I get a feel for how much memory my functions use?
https://nodemcu.readthedocs.io/en/maste ... ctions-use

What is the cost of using functions?
https://nodemcu.readthedocs.io/en/maste ... ctions-use

Functions have fixed overheads, so in general the more that you group your application code into larger functions, then the less RAM used will be used overall. The main caveat here is that if you are starting to do "copy and paste" coding across functions then you are wasting resources. So of course you should still use functions to structure your code and encapsulate common repeated processing, but just bear in mind that each function definition has a relatively high overhead for its header record and stack frame. So try to avoid overusing functions. If there are less than a dozen or so lines in the function then you should consider putting this code inline if it makes sense to do so.

What other resources are available?
https://nodemcu.readthedocs.io/en/maste ... -available

Firmware and Lua app development
How to reduce the size of the firmware?
https://nodemcu.readthedocs.io/en/maste ... e-firmware

Extension Developer FAQ
Firmware build options
https://nodemcu.readthedocs.io/en/maste ... loper-faq/

Hardware FAQ
https://nodemcu.readthedocs.io/en/maste ... dware-faq/

Reading notes on Closure - PilEd4Ch9Pg68

Functions in Lus are first-class values, meaning that, in Lua a function is a value with the same rights as more conventional values like numbers and strings.

Functions have “lexical scoping”, meaning that functions can access variables of their enclosing functions.

Functional programming techniques can make your programs smaller and simpler.

Functions as values, can be created by expressions, eg, foo = function (x) return 2*x end

Function definition such as function foo (x) return 2*x end is syntactic sugar of above.

Function definition is in fact a statement that creates a value of type "function" and assigns it to a variable.

Functions are anonymous, meaning that like any other value, they do not have names.

Function name, such as print, we are actually talking about a variable that holds that function. Although we often assign functions to global variables, giving them something like a name, there are several occasions when functions remain anonymous. An anonmous function example is the higher oder function table.sort, which takes another (anonymous) function, eg, table.sort(exampleTable, function (a,b) return (a.name > b.name) end)

Functions as first class values can be stored not only in global variables, but also in table fields and in local variables.

Functions can be stored in a local variable, as a local function, in a chunk, meaning that Lexical scoping ensures that other functions in the chunk can use these local functions.

Lexical Scoping - Ch9pg71

A Taste of Functional Programming - Ch9pg74

Upvalues - Ch9pg260

While the registry offers global variables, the upvalue mechanism implements an equivalent of C static variables that are visible only inside a particular function. Every time we create a new C function in Lua, we can associate with it any number of upvalues, each one holding a single Lua value. Later, when we call the function, it has free access to any of its upvalues, using pseudo-indices.

We call this association of a C function with its upvalues a closure. A C closure is a C approximation to a Lua closure. In particular, we can create different closures using the same function code, but with different upvalues.

Re: GPIO.input voltage levels vs edge detection

Posted: Wed Nov 14, 2018 1:59 pm
by tlfong01
tlfong01 wrote:
Wed Nov 14, 2018 7:15 am
NodeMCU Lua Newbie Debugging Tips

ESP8266 RAM vs Rpi RAM vs Arduino RAM

So now I know ESP8266 has miserably little memory of the order 50k to 100k. This reminds me that Arduino has even much smaller, only 1k to 8k bytes. I still remember the Arduino memory advice I read in the appendix and followed them all, but still found it impossible to do what I wanted to do. That is why I gave up Arduino and switched to Rpi. Now for ESP8266 I have a similar memory problem, only about 50k to 100k, though 10 times more than Arduino.

Anyway, I know I cannot write any big programs to run in ESP8266. So I will follow the NodeMCU FAQ's advice to keep everything simple, and do simple things in ESP, and let Rpi do the big things.

Appendix A - Arduino memory problem

Arduino Memory Notes
https://www.arduino.cc/en/Tutorial/Memory

The ATmega328 chip found on the Uno has the following amounts of memory:
Flash 32k bytes (of which .5k is used for the bootloader)
SRAM 2k bytes
EEPROM 1k byte

The ATmega2560 in the Mega2560 has larger memory space :
Flash 256k bytes (of which 8k is used for the bootloader)
SRAM 8k bytes
EEPROM 4k byte

Notice that there's not much SRAM available in the Uno. It's easy to use it all up by having lots of strings in your program. For example, a declaration like:

char message[] = "I support the Cape Wind project.";

puts 33 bytes into SRAM (each character takes a byte, plus the '\0' terminator). This might not seem like a lot, but it doesn't take long to get to 2048, especially if you have a large amount of text to send to a display, or a large lookup table, for example.

If you run out of SRAM, your program may fail in unexpected ways;

it will appear to upload successfully, but not run, or run strangely.


To check if this is happening, you can try commenting out or shortening the strings or other data structures in your sketch (without changing the code). If it then runs successfully, you're probably running out of SRAM. There are a few things you can do to address this problem:

If your sketch talks to a program running on a (desktop/laptop) computer, you can try shifting data or calculations to the computer, reducing the load on the Arduino.

If you have lookup tables or other large arrays, use the smallest data type necessary to store the values you need; for example, an int takes up two bytes, while a byte uses only one (but can store a smaller range of values).

If you don't need to modify the strings or data while your sketch is running, you can store them in flash (program) memory instead of SRAM; to do this, use the PROGMEM keyword.

Re: GPIO.input voltage levels vs edge detection

Posted: Thu Nov 15, 2018 5:22 am
by tlfong01
tlfong01 wrote:
Wed Nov 14, 2018 7:15 am
NodeMCU / ESPlorer instability problem again!
However, as I am trying to add a little bit more code to the stable version, I again found problems.
ESPlorer sometimes mysteriously executes old version or part of old version of a program, even when new version is uploaded and executed!
NodeMCU Lua Newbie Debugging Tips - Part 1
I goggled and skimmed through some good references and found the reasons why my newbieBlink program is unstable and often cause panic reboot of the ESP8366SDK/NodeMCU runtime.
There are also other important things I need to know in using ESP8266

NodeMCU Lua Newbie Debugging Tips - Part 2

As NodeMCU firmware FAQ says, version 2.x on ESP8266-12EX is not an OS, but a very small runtime with very limited debug features, without eLua debug and os modules. FAQ suggests 1980's primitive debugging methods of binary chop and print statements. Node.JS programmers experienced in event driven programming might not complain, but ESP8266 newbies should find binary chop printing debugging approaches mission impossible, ...

For newbies, I would recommend the software development methods TDD (Test Driven Development), CI (Continuous Integration), and CD (Continuous Delivery). I have been using these approaches (along with other principles, such as structured programming, top down design, step wise bottom up refinement and implementation, open close, functional programming etc) and found my newbieBlink program writing, though slow, but progressing steadily.

Let me do a selfie walk through of newbieBlink now.

1. I first started with a humble goal of switching on the built in LED for two seconds, using a timer lowTime with a corresponding callback function.

2. Then I wrote a similar highTimer to switch off the LED for four seconds.

3. Then I wrote a third taskTimer with a task counter, to start the highTimer with an initial toggle count.

4. highTimer callback function starts lowTimer, whose callback loops back to start the highTimer which repeats the loop until toggle count is up, and calls taskTimer, which repeats highTimer, until task count is up.

5. the algorithm sounds a bit complicated, but I have been doing in very small steps, continuously integrating second timer functions to first timer, then third timer to the previous two timers. For the third timer, I actually start with a broken version, then step by step add more things to complete the third timer.

6. For every step above, I save the debugged version as a built, and keep all the builts as I go along. Whenever I found the nodeMCU panic and reboots, I don't need to do any binary chop, or even print, because I am very confident it is the last thing I added that causes the runtime panic.

7. I am only using the interpreter mode, no compilation, so the development process is fast (I can continuously do integration and deliveries many times in an hour!), at least comparing with Arduino IDE C++ or micropython (again in Mr green's opinion) . :mrgreen:

Appendix A - NodeMCU FAQ on debugging

The ESP8266 runs the SDK over the native hardware, so there is no underlying operating system to capture errors and to provide graceful failure modes. Hence system or application errors can easily "PANIC" the system causing it to reboot.

Error handling has been kept simple to save on the limited code space, and this exacerbates this tendency. Running out of a system resource such as RAM will invariably cause a messy failure and system reboot.

There is currently no debug library support. So you have to use 1980s-style "binary-chop" to locate errors and use print statement diagnostics though the system's UART interface.

The various libraries (net, tmr, wifi, etc.) use the SDK callback mechanism to bind Lua processing to individual events (for example a timer alarm firing). Developers should make full use of these events to keep Lua execution sequences short.

Stacking up such requests in a single Lua task function burns scarce RAM and can trigger a PANIC. This is true for timer, network, and other callbacks.


Appendix B - Wikipedia on Software development methods

Test Driven Development - Wikipedia
https://en.wikipedia.org/wiki/Test-driven_development

Test Driven Development (TDD) is a software development process that relies on the repetition of a very short development cycle: requirements are turned into very specific test cases, then the software is improved to pass the new tests, only. This is opposed to software development that allows software to be added that is not proven to meet requirements.

Kent Beck is credited with having developed or rediscovered the technique, stated in 2003 that TDD encourages simple designs and inspires confidence.


Continuous Integration - Wikipedia
https://en.wikipedia.org/wiki/Continuous_integration

Continuous Integration (CI) is the practice of merging all developer working copies to a shared mainline several times a day.

Grady Booch first proposed the term CI in his 1991 method, although he did not advocate integrating several times a day. Extreme programming (XP) adopted the concept of CI and did advocate integrating more than once per day – perhaps as many as tens of times per day.


Continuous Delivery - Wikipedia
https://en.wikipedia.org/wiki/

Continuous Delivery (CD) is a software engineering approach in which teams produce software in short cycles, ensuring that the software can be reliably released at any time.

It aims at building, testing, and releasing software with greater speed and frequency. The approach helps reduce the cost, time, and risk of delivering changes by allowing for more incremental updates to applications in production. A straightforward and repeatable deployment process is important for continuous delivery.

Re: GPIO.input voltage levels vs edge detection

Posted: Fri Nov 16, 2018 7:39 am
by tlfong01
tlfong01 wrote:
Wed Nov 14, 2018 7:15 am
NodeMCU / ESPlorer instability problem again!
However, as I am trying to add a little bit more code to the stable version, I again found problems.
ESPlorer sometimes mysteriously executes old version or part of old version of a program, even when new version is uploaded and executed!
NodeMCU Lua Newbie Debugging Tips
Two important things I have been ignorant are the following:
1. How to declare local and global values.
I don't know that by default any variable that is referenced and not previously declared as local is global and this variable will persist in the global table until it is explicitly deleted. I guess this is why I thought ESPlorer executes old code. Actually some my timer callback functions of old and new version get messed up and cause wierd things happening.
2. How to delete global values no longer necessary.

newbieBlink Version 14.01.01 with easy debug print statements

Earlier I found that if there are two timers or functions of different versions of a program, when I run the new version, it is the old version timer/function that will run, thus misleading me and other newbies thinking that the new version program file is not saved or uploaded. Actually the program file has always been uploaded successfully.

One other laughable thing is that, if I deleted an function is the new version, but forgot to delete a call to the deleted function, the IDE runtime will kind heartedly find the old version of function and execute it.

I am worrying that more unexpected thing might happen from time to time, so I have added print statements for the stable version of blink and use it as the new stable benchmark version. The debug print output and full listing is displayed below.
...

Code: Select all

program                    =	newbieBlinkV14.01.01 2018nov16hkt1519
  function                 =    togglePin01
    pinNum                 =	4
    highTime               =	100
    lowTime                =	100
    initToggleCount        =	2
    toggleDelayTime        =	500
    initTaskCount          =	4

Begin toggle tasks.
  Now starting taskTimer.
>   currentTaskCount         =	1
    Now starting highTimer.
      currentToggleCount   =	1
        Now starting lowTimer
      currentToggleCount   =	2
        Now starting lowTimer
      currentToggleCount   =	3
  Now starting taskTimer.
  currentTaskCount         =	2
    Now starting highTimer.
      currentToggleCount   =	1
        Now starting lowTimer
      currentToggleCount   =	2
        Now starting lowTimer
      currentToggleCount   =	3
  Now starting taskTimer.
  currentTaskCount         =	3
    Now starting highTimer.
      currentToggleCount   =	1
        Now starting lowTimer
      currentToggleCount   =	2
        Now starting lowTimer
      currentToggleCount   =	3
  Now starting taskTimer.
  currentTaskCount         =	4
    Now starting highTimer.
      currentToggleCount   =	1
        Now starting lowTimer
      currentToggleCount   =	2
        Now starting lowTimer
      currentToggleCount   =	3
  Now starting taskTimer.
  currentTaskCount         =	5
  End   toggle tasks.
Now stopping all timers.
...
...

Code: Select all

title = 'newbieBlinkV14.01.01 2018nov16hkt1519'

High   = true;  Low   = false
Output = true;  Input = false
D0 = 0;  D1 = 1;  D2 = 2;  D3 = 3 
D4 = 4;  D5 = 5;  D6 = 6;  D7 = 7 
D8 = 8
TenthSecond  =  100;  EighthSecond  =   125
FifthSecond   = 200;  QuarterSecond =   250
HalfSecond   =  500;  OneSecond     =  1000
TwoSeconds   = 2000;  FourSeconds   =  4000
EightSeconds = 8000;  TenSeconds    = 10000
OneTime    = 1;  TwoTimes   = 2;  ThreeTimes = 3 
FourTimes  = 4;  FiveTimes  = 5;  SixTimes = 6
SevenTimes = 7;  EightTimes = 8

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

 function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

 function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

 function setAllPinsOutput()
  for i = 0, 8, 1
    do
      setPinMode(i, Output)
  end
end

 function setAllPinsLow()
  for i = 0, 8, 1
    do
      setPinLow(i)
  end
end

 function setupPins()
  setAllPinsOutput()
  setAllPinsLow()
end

function togglePin01(pinTable)

  pinNum	   = pinTable.pinNum
  highTime	   = pinTable.highTime
  lowTime	   = pinTable.lowTime
  initToggleCount  = pinTable.totalToggleCount
  toggleDelayTime  = pinTable.toggleDelayTime
  initTaskCount	   = pinTable.totalTaskCount

  print('  function                 =    togglePin01')
  print('    pinNum                 =', pinNum)
  print('    highTime               =', highTime)
  print('    lowTime                =', lowTime)
  print('    initToggleCount        =', initToggleCount)
  print('    toggleDelayTime        =', toggleDelayTime)
  print('    initTaskCount          =', initTaskCount)

   highTimer01 = tmr.create()
   lowTimer01  = tmr.create()
   taskTimer01 = tmr.create()

  function taskTimerCallback01()
    print('  currentTaskCount         =', currentTaskCount)
      if currentTaskCount <= initTaskCount
        then
          currentTaskCount = currentTaskCount + 1
          currentToggleCount = 1
          setPinHigh(pinNum)
	  print('    Now starting highTimer.')
          highTimer01:start()
        else
	  print('  End   toggle tasks.')
	  print('Now stopping all timers.')
	  highTimer01:stop()
	  lowTimer01:stop()
	  taskTimer01:stop()
      end 
  end

   function highTimerCallback01()
    setPinLow(pinNum) 
    print('      currentToggleCount   =', currentToggleCount)
    if currentToggleCount <= initToggleCount
      then        
        currentToggleCount = currentToggleCount + 1
	print('        Now starting lowTimer')
        lowTimer01:start()
      else
        print('  Now starting taskTimer.')
	taskTimer01:start()
    end
  end

   function lowTimerCallback01()
    setPinHigh(pinNum)  
    highTimer01:start()
  end

  highTimer01:register(highTime,        tmr.ALARM_SEMI, highTimerCallback01)
  lowTimer01 :register (lowTime,        tmr.ALARM_SEMI, lowTimerCallback01)
  taskTimer01:register(toggleDelayTime, tmr.ALARM_SEMI, taskTimerCallback01)

  print('')
  print('Begin toggle tasks.')
  currentTaskCount = 1
  print('  Now starting taskTimer.')
  taskTimer01:start()

end

 pinTable01 = 
  {
    pinNum          = D4,
    highTime        = TenthSecond, 
    lowTime         = TenthSecond, 
    totalToggleCount = TwoTimes, 
    toggleDelayTime = HalfSecond,
    totalTaskCount   = FourTimes
  }

--]]

 function main()
  print('program                    =', title)
  setupPins()
  togglePin01(pinTable01)
end

main()  

Re: GPIO.input voltage levels vs edge detection

Posted: Fri Nov 16, 2018 7:41 am
by tlfong01
tlfong01 wrote:
Wed Nov 14, 2018 7:15 am
NodeMCU / ESPlorer instability problem again!
However, as I am trying to add a little bit more code to the stable version, I again found problems.
ESPlorer sometimes mysteriously executes old version or part of old version of a program, even when new version is uploaded and executed!
NodeMCU Lua Newbie Debugging Tips
Two important things I have been ignorant are the following:
1. How to declare local and global values.
I don't know that by default any variable that is referenced and not previously declared as local is global and this variable will persist in the global table until it is explicitly deleted. I guess this is why I thought ESPlorer executes old code. Actually some my timer callback functions of old and new version get messed up and cause wierd things happening.
2. How to delete global values no longer necessary.

Errata 2018nov16hkt1542

I seem to have by mistake duplicated this post. So I shall delete this one later. My apology for any confusion.


newbieBlink Version 14.01.01 with easy debug print statements

Earlier I found that if there are two timers or functions of different versions of a program, when I run the new version, it is the old version timer/function that will run, thus misleading me and other newbies thinking that the new version program file is not saved or uploaded. Actually the program file has always been uploaded successfully.

One other laughable thing is that, if I deleted an function is the new version, but forgot to delete a call to the deleted function, the IDE runtime will kind heartedly find the old version of function and execute it.

I am worrying that more unexpected thing might happen from time to time, so I have added print statements for the stable version of blink and use it as the new stable benchmark version. The debug print output and full listing is displayed below.
...

Code: Select all

program                    =	newbieBlinkV14.01.01 2018nov16hkt1519
  function                 =    togglePin01
    pinNum                 =	4
    highTime               =	100
    lowTime                =	100
    initToggleCount        =	2
    toggleDelayTime        =	500
    initTaskCount          =	4

Begin toggle tasks.
  Now starting taskTimer.
>   currentTaskCount         =	1
    Now starting highTimer.
      currentToggleCount   =	1
        Now starting lowTimer
      currentToggleCount   =	2
        Now starting lowTimer
      currentToggleCount   =	3
  Now starting taskTimer.
  currentTaskCount         =	2
    Now starting highTimer.
      currentToggleCount   =	1
        Now starting lowTimer
      currentToggleCount   =	2
        Now starting lowTimer
      currentToggleCount   =	3
  Now starting taskTimer.
  currentTaskCount         =	3
    Now starting highTimer.
      currentToggleCount   =	1
        Now starting lowTimer
      currentToggleCount   =	2
        Now starting lowTimer
      currentToggleCount   =	3
  Now starting taskTimer.
  currentTaskCount         =	4
    Now starting highTimer.
      currentToggleCount   =	1
        Now starting lowTimer
      currentToggleCount   =	2
        Now starting lowTimer
      currentToggleCount   =	3
  Now starting taskTimer.
  currentTaskCount         =	5
  End   toggle tasks.
Now stopping all timers.
...
...

Code: Select all

title = 'newbieBlinkV14.01.01 2018nov16hkt1519'

High   = true;  Low   = false
Output = true;  Input = false
D0 = 0;  D1 = 1;  D2 = 2;  D3 = 3 
D4 = 4;  D5 = 5;  D6 = 6;  D7 = 7 
D8 = 8
TenthSecond  =  100;  EighthSecond  =   125
FifthSecond   = 200;  QuarterSecond =   250
HalfSecond   =  500;  OneSecond     =  1000
TwoSeconds   = 2000;  FourSeconds   =  4000
EightSeconds = 8000;  TenSeconds    = 10000
OneTime    = 1;  TwoTimes   = 2;  ThreeTimes = 3 
FourTimes  = 4;  FiveTimes  = 5;  SixTimes = 6
SevenTimes = 7;  EightTimes = 8

function setPinMode(pinNum, pinMode)
  if pinMode == Output
    then
      gpio.mode(pinNum, gpio.OUTPUT)  
    else
      gpio.mode(pinNum, gpio.INPUT) 
  end
end

 function setPinHigh(pinNum)
  gpio.write(pinNum, gpio.HIGH)  
end

 function setPinLow(pinNum)
  gpio.write(pinNum, gpio.LOW)  
end

 function setAllPinsOutput()
  for i = 0, 8, 1
    do
      setPinMode(i, Output)
  end
end

 function setAllPinsLow()
  for i = 0, 8, 1
    do
      setPinLow(i)
  end
end

 function setupPins()
  setAllPinsOutput()
  setAllPinsLow()
end

function togglePin01(pinTable)

  pinNum	   = pinTable.pinNum
  highTime	   = pinTable.highTime
  lowTime	   = pinTable.lowTime
  initToggleCount  = pinTable.totalToggleCount
  toggleDelayTime  = pinTable.toggleDelayTime
  initTaskCount	   = pinTable.totalTaskCount

  print('  function                 =    togglePin01')
  print('    pinNum                 =', pinNum)
  print('    highTime               =', highTime)
  print('    lowTime                =', lowTime)
  print('    initToggleCount        =', initToggleCount)
  print('    toggleDelayTime        =', toggleDelayTime)
  print('    initTaskCount          =', initTaskCount)

   highTimer01 = tmr.create()
   lowTimer01  = tmr.create()
   taskTimer01 = tmr.create()

  function taskTimerCallback01()
    print('  currentTaskCount         =', currentTaskCount)
      if currentTaskCount <= initTaskCount
        then
          currentTaskCount = currentTaskCount + 1
          currentToggleCount = 1
          setPinHigh(pinNum)
	  print('    Now starting highTimer.')
          highTimer01:start()
        else
	  print('  End   toggle tasks.')
	  print('Now stopping all timers.')
	  highTimer01:stop()
	  lowTimer01:stop()
	  taskTimer01:stop()
      end 
  end

   function highTimerCallback01()
    setPinLow(pinNum) 
    print('      currentToggleCount   =', currentToggleCount)
    if currentToggleCount <= initToggleCount
      then        
        currentToggleCount = currentToggleCount + 1
	print('        Now starting lowTimer')
        lowTimer01:start()
      else
        print('  Now starting taskTimer.')
	taskTimer01:start()
    end
  end

   function lowTimerCallback01()
    setPinHigh(pinNum)  
    highTimer01:start()
  end

  highTimer01:register(highTime,        tmr.ALARM_SEMI, highTimerCallback01)
  lowTimer01 :register (lowTime,        tmr.ALARM_SEMI, lowTimerCallback01)
  taskTimer01:register(toggleDelayTime, tmr.ALARM_SEMI, taskTimerCallback01)

  print('')
  print('Begin toggle tasks.')
  currentTaskCount = 1
  print('  Now starting taskTimer.')
  taskTimer01:start()

end

 pinTable01 = 
  {
    pinNum          = D4,
    highTime        = TenthSecond, 
    lowTime         = TenthSecond, 
    totalToggleCount = TwoTimes, 
    toggleDelayTime = HalfSecond,
    totalTaskCount   = FourTimes
  }

--]]

 function main()
  print('program                    =', title)
  setupPins()
  togglePin01(pinTable01)
end

main()  

Re: GPIO.input voltage levels vs edge detection

Posted: Fri Nov 16, 2018 2:12 pm
by tlfong01
tlfong01 wrote:
Thu Nov 08, 2018 4:06 am
Testing NodeMCU board with big 100uF 6V3 tatalum capacitor
I still find the 8 Wemos NodeMCU boards have intermittent failures on running the NewbieBlink V10. I now suspect that the boards do not have stable performance because they do not have a good power supply.

I checked the AMS1117 low drop out voltage regulator IC and found its guaranteed drop out of 1.3V at 1A rated output at 5V is OK. The USB 5V power measured 4.6/4.8V at the board and static Vcc 3.25V looks good.

Update - On second thought, this might be marginal.

Anyway, I think it a good idea to test a board with a big cap, and also UART to TTL cable compatible can perhaps makes it easier to debug.

Comparing fake NodeMCU V3, Wemos D1 Mini and Amica boards

So I have been testing my newbieBlink program using about 8 to 10 esp8266 nodemcu boards of three types, from different reputable TaoBao shops, Wemos D1 Mini/MiniPro, Amica and no brand NodeMCU V3 boards.

So far so good, until this afternoon when I have been non stop testing newbieBlink for a couple of hours.

I found that the two used to be stable software master versions with more than one identical read only copies started to show intermittent failures, with different error messages. After some board/cable swap troubleshooting, I quickly concluded the following:

1. The Wemos D1 Mini board power supply, logic, or wifi circuit very likely heated up and caused more often than usual execution failures (not uploading failures, I think).

2. I also swapped long and short, good quality (double shielded) and poor quality the USB 2.0/3.0 cables, with or without the USB hub. I also concluded with confidence that the USB cable also causes the intermittent failures.

I checked that the the Wemos circuits uses only 10uF caps at each of the power and logic chips, and I guess this is not that reliable comparing the 100uF used in the bigger size Amica and no brand boards.

So from now on, I will only do the following:

1. Use the big boards with 100uF caps

2. Direct connect USB cable to PC USB socket, and not through the USB hub.

3. Swap heated up nodeMCU boards as soon as I find more frequent intermittent errors after long hours of testing.