- By means of a module RCWL0516 the movement.
By means of a DHT11 module, the temperature and humidity of the room.
By means of an LDR resistor, the level of illumination.
Each time the motion sensor in the room is activated, it sends a message to the base station, which records the room number, the type of event and its value and adds the date and time it occurred.
With the periodicity that we establish, we check if the temperature, humidity and / or light level have varied, within adjustable limits, and send the corresponding message.
The first stumbling block I found is that, in its current state, the implementation of the W5500 module in Annex does not allow to use NTP synchronization, nor to upload the results to an external server using FTP, nor to send eMails.
But everything has a solution: ETHERNET.WGET$ works perfectly and I have used it to obtain our public IP, synchronize the current date / time and upload the collected data to the thingspeak.com server.
I should point out that this entire system is, in fact, a manifest intrusion into the private lives of our loved ones, but in today's sad circumstances of forced estrangement and loneliness, it can be vital in detecting bouts of depression or symptoms of physical illness prematurely through the statistical study of their daily habits and customs.
How to do it:
We recorded the ESP32 with the option "Flash firmware only". We connect to it through the address 192.168.4.1 and leave the entire configuration page blank, except for the name of the access point, the “Autorun file” and the username and password of the “Protected acces”, since the station will be visible to our neighbors:
We connect the W5500 module: And we load the program ethernet_min.bas
Code: [Local Link Removed for Guests]
' *************************
' ** EspNow and Ethernet **
' ** V0.0 14/04/21 **
' *************************
' Write API key of our account in thingspeak.com
API_KEY$ = "xxxxxxxxxxxxxxxx"
' pin scs of W5500 to pin GPIO15 of ESP32
Ethernet 15, "http://www.vermiip.es/vermiip/muestraip.php"
' time offset from our country = 2
NTP 2, "http://free.timeanddate.com/clock/i7q6n1qi/n1440/tles4/tt0/tw0/tm3/td2/th1/tb1"
' turn on the network
ok = espnow.begin
if ok = 0 then wlog "Mode ESPNOW active" else wlog "Fail ESPNOW activate"
onEspNowMsg message
wait
END
' ---------------------------------------------------------------
message:
' message struct: room number, event type, value
' event type: (M)otion, (T)emperature, (H)umidity, (L)ight
message$ = espnow.read$
room$ = word$(message$, 1, ","))
event$ = word$(message$, 2, ",")
value$ = word$(message$, 3, ",")
thingspeak room$, event$, value$
return
' ---------------------
SUB Ethernet(scs, url$)
' ---------------------
LOCAL ok, a$
ok = ethernet.init(scs) ' SCS W5500 to GPIO15
if ok < 1 then END
a$ = ethernet.IP$
wlog "IP: " + word$(a$,1)
wlog "Mask: " + word$(a$,2)
wlog "Gateway: " + word$(a$,3)
a$ = ethernet.wget$(url$)
wlog "Public IP: " + word.extract$(a$, "<strong>", "</strong>")
END SUB
' -------------------
SUB NTP(offset, url$)
' -------------------
LOCAL t$
LOCAL year, month, day, hour, minute, second
t$ = ethernet.wget$(url$)
t$ = word.extract$(t$, "<span id=t1>", "</span>")
wlog t$
year = val(mid$(t$, 9, 2))
month = val(mid$(t$, 4, 2))
day = val(mid$(t$, 1, 2))
hour = val(mid$(t$,13, 2)) + offset
minute = val(mid$(t$, 16,2))
second = val(mid$(t$, 19, 2))
SETTIME year, month, day, hour, minute, second
wlog date$, time$
END SUB
' -----------------------------------
SUB thingspeak(room$, event$, value$)
' -----------------------------------
LOCAL g$
g$ = "api.thingspeak.com/update?api_key=" + API_KEY$
g$ = g$ + "&field1=" + room$
g$ = g$ + "&field2=" + event$
g$ = g$ + "&field3=" + value$
g$ = g$ + "&field4=" + date$
g$ = g$ + "&field5=" + time$
wlog ethernet.wget$(g$, 80)
END SUB
Code: [Local Link Removed for Guests]
' *********************
' ** EspNow Sensors **
' ** V1.0 14/04/21 **
' *********************
' event type: (M)otion, (T)emperature, (H)umidity, (L)ight
' message structure: room,event,value
' last measure:
Tprev = 0 : Hprev = 0 :Lprev = 0
Id$ = "0" ' identifier of this unit
message$ = ""
' start network espnow
rMAC$ = "CC:50:E3:92:5E:41" ' address of the receiver
ok = espnow.begin
if ok = 0 then wlog "ESPNOW ON" else wlog "ESPNOW FAIL"
espnow.add_peer rMAC$
onEspNowError status
' motion sensor RCWL0516
pin.mode 12, input
interrupt 12, RCWL0516
' temperature/humidity sensor DHT11
DHT.SETUP 2, 11
timer0 30000, sampling ' sample sensors every 30 seconds
wait
END
' ----------------------
sendmessage:
espnow.write(message$, rMAC$)
wlog message$
return
' ----------------------
status:
wlog "TX error on "; espnow.error$ ' print the error
return
' ----------------------
RCWL0516:
if pin(12) = 0 then return
message$ = Id$ + ",M,1" ' Motion detected
gosub sendmessage
return
' ----------------------
sampling:
T = DHT.TEMP
if (T<=(Tprev-1)) OR (T>=(Tprev+1)) then
message$ = Id$ + ",T," + str$(T) ' send temperature
gosub sendmessage
Tprev = T
end if
H = DHT.HUM
if (H<=(Hprev-5)) OR (H>=(Hprev+5)) then
message$ = Id$ + ",H," + str$(H) ' send humidity
gosub sendmessage
Hprev = H
end if
L = ADC
if (L<=(Lprev-20)) OR (L>=(Lprev+20)) then
message$ = Id$ + ",L," + str$(cint(L)) ' send brightness
gosub sendmessage
Lprev = L
end if
return
But we all know that since 1990 more attention has been paid to the visual aesthetics of the application than to its content ...
The result is this:
Code: [Local Link Removed for Guests]
' *************************
' ** EspNow and Ethernet **
' ** V1.0 14/04/21 **
' *************************
' Write API key of our account in thingspeak.com
API_KEY$ = "xxxxxxxxxxxxxxxx"
' message type: (M)otion, (T)emperature, (H)umidity, (L)ight
DIM type$(3) = "M", "T", "H", "L"
' rooms of the house:
DIM room$(5) = "cocina", "salon", "servicio", "invitados", "bano", "dormitorio"
lastRoom = 0 ' Where was the last time?
' pin scs of W5500 to pin GPIO15 of ESP32
Ethernet 15, "http://www.vermiip.es/vermiip/muestraip.php"
' time offset from our country = 2
NTP 2, "http://free.timeanddate.com/clock/i7q6n1qi/n1440/tles4/tt0/tw0/tm3/td2/th1/tb1"
' start log file
file$ = "" : line$ = "Connect at " + time$ + " " + date$
dailyLog line$
' turn on the network
ok = espnow.begin
if ok = 0 then wlog "Mode ESPNOW active" else wlog "Fail ESPNOW activate"
onEspNowMsg message
onhtmlreload plano
gosub plano
'timer0 1000, simulacrum ' comment in final version
wait
END
' ---------------------------------------------------------------
message:
message$ = espnow.read$
wlog message$
gosub update
line$ = message$ + "," + time$ + "," + date$
dailyLog line$
wlog line$
' thingspeak room, event$, value$
return
' ---------------------------------------------------------------
update:
' message struct: room number, event type, value
room = val(word$(message$, 1, ","))
event$ = word$(message$, 2, ",")
value$ = word$(message$, 3, ",")
select case event$
case "M" ' Motion
css cssId$(room$(lastRoom),"fill:white; stroke:white;")
css cssId$(room$(room), "fill:#ffffaa; stroke:#ff7f00; stroke-width:5;")
lastRoom = room
case "T" ' Temperature
value$ = value$ + "º"
case "H" ' Humidity
value$ = value$ + "%"
case "L" ' Light
value$ = value$ + " lx"
end select
if event$ <> "M" then
j$ = "document.getElementById('" + event$ + str$(room) + "').textContent = '" + value$ + "';"
wlog j$
jscall j$
end if
return
' ---------------------------------------------------------------
simulacrum:
message$ = str$(rnd(6)) + "," + type$(rnd(4)) + "," + str$(rnd(100))
wlog message$
gosub update
return
' ---------------------
SUB Ethernet(scs, url$)
' ---------------------
LOCAL ok, a$
ok = ethernet.init(scs) ' SCS W5500 to GPIO15
select case ok
case 0 : wlog "Failed to receive a DHCP IP"
case 1 : wlog "DHCP IP received successfully"
case 2 : wlog "Using a manually configured fixed IP address"
case -1 : wlog "Ethernet module not found"
case -2 : wlog "UTP cable is not connected"
end select
if ok < 1 then END
a$ = ethernet.IP$
wlog "IP: " + word$(a$,1)
wlog "Mask: " + word$(a$,2)
wlog "Gateway: " + word$(a$,3)
a$ = ethernet.wget$(url$)
wlog "Public IP: " + word.extract$(a$, "<strong>", "</strong>")
END SUB
' -------------------
SUB NTP(offset, url$)
' -------------------
LOCAL t$
LOCAL year, month, day, hour, minute, second
t$ = ethernet.wget$(url$)
t$ = word.extract$(t$, "<span id=t1>", "</span>")
wlog t$
year = val(mid$(t$, 9, 2))
month = val(mid$(t$, 4, 2))
day = val(mid$(t$, 1, 2))
hour = val(mid$(t$,13, 2)) + offset
minute = val(mid$(t$, 16,2))
second = val(mid$(t$, 19, 2))
SETTIME year, month, day, hour, minute, second
wlog date$, time$
END SUB
' -----------------
SUB dailyLog(line$)
' -----------------
file$ = "/dat" + right$(date$, 2) + mid$(date$, 4, 2) + left$(date$, 2) + ".txt"
line$ = line$ + chr$(13)
if file.exists(file$) then
file.append file$, line$
else
file.save file$, line$
end if
END SUB
' ----------------------------------
SUB thingspeak(room, event$, value$)
' ----------------------------------
LOCAL g$
g$ = "api.thingspeak.com/update?api_key=" + API_KEY$
g$ = g$ + "&field1=" + str$(room) + "&field2=" + event$ + "&field3=" + value$
g$ = g$ + "&field4=" + date$ + "&field5=" + time$
wlog ethernet.wget$(g$, 80)
END SUB
' -------------------------------------------------------------------------------------
plano:
cls
a$ = ""
a$ = a$ + |<center>|
a$ = a$ + |<svg width="768" height="747">|
' <!-- Walls -->
a$ = a$ + |<g style="fill:#666666;">|
a$ = a$ + |<rect x="8" y="5" width="8" height="372"/>|
a$ = a$ + |<rect x="8" y="418" width="8" height="142"/>|
a$ = a$ + |<rect x="8" y="652" width="8" height="84"/>|
a$ = a$ + |<rect x="16" y="728" width="386" height="8"/>|
a$ = a$ + |<rect x="394" y="580" width="8" height="148"/>|
a$ = a$ + |<rect x="394" y="572" width="25" height="8"/>|
a$ = a$ + |<rect x="472" y="572" width="21" height="8"/>|
a$ = a$ + |<rect x="485" y="443" width="8" height="129"/>|
a$ = a$ + |<rect x="492" y="443" width="265" height="8"/>|
a$ = a$ + |<rect x="749" y="49" width="8" height="394"/>|
a$ = a$ + |<rect x="698" y="49" width="53" height="8"/>|
a$ = a$ + |<rect x="512" y="49" width="115" height="8"/>|
a$ = a$ + |<rect x="247" y="49" width="57" height="8"/>|
a$ = a$ + |<rect x="201" y="45" width="47" height="8" transform="rotate(11 225 48)"/>|
a$ = a$ + |<rect x="14" y="9" width="47" height="8" transform="rotate(11 37 14)"/></g>|
' <!-- Windows -->
a$ = a$ + |<g style="fill:#aaffff; stroke:#b2b2b2; stroke-width:2;">|
a$ = a$ + |<rect x="8" y="561" width="8" height="90"/>|
a$ = a$ + |<rect x="8" y="378" width="8" height="40"/>|
a$ = a$ + |<rect x="59" y="29" width="144" height="8" transform="rotate(11 140 29)"/>|
a$ = a$ + |<rect x="303" y="48" width="208" height="8"/>|
a$ = a$ + |<rect x="628" y="48" width="69" height="8"/></g>|
' <!-- Sliding door -->
a$ = a$ + |<rect x="632" y="171" width="70" height="8" fill="#aaffff" stroke="#b2b2b2" stroke-width="2" />|
a$ = a$ + |<line x1="615" x2="676" y1="170" y2="170" stroke="#0000ff" stroke-width="3"/>|
a$ = a$ + |<line x1="592" x2="644" y1="180" y2="180" stroke="#0000ff" stroke-width="3"/>|
' <!-- Doors -->
a$ = a$ + |<g style="fill:none; stroke:#cccccc;">|
a$ = a$ + |<rect x="420" y="571" width="51" height="9" id="front_door"/>|
a$ = a$ + |<rect x="485" y="382" width="8" height="50"/>|
a$ = a$ + |<rect x="376" y="355" width="104" height="8" />|
a$ = a$ + |<rect x="362" y="370" width="8" height="50"/>|
a$ = a$ + |<rect x="180" y="355" width="50" height="8" />|
a$ = a$ + |<rect x="171" y="426" width="50" height="8" />|
a$ = a$ + |<rect x="154" y="370" width="8" height="50"/>|
a$ = a$ + |<rect x="296" y="533" width="50" height="8" /></g>|
' <!-- Interior walls -->
a$ = a$ + |<g style="stroke:#56ffaa; stroke-width:8;">|
a$ = a$ + |<line x1="245" y1="57" x2="245" y2="356"/>|
a$ = a$ + |<line x1="588" y1="57" x2="588" y2="356"/>|
a$ = a$ + |<line x1="592" y1="175" x2="630" y2="175"/>|
a$ = a$ + |<line x1="704" y1="175" x2="749" y2="175"/>|
a$ = a$ + |<line x1="16" y1="359" x2="178" y2="359"/>|
a$ = a$ + |<line x1="233" y1="359" x2="374" y2="359"/>|
a$ = a$ + |<line x1="482" y1="359" x2="592" y2="359"/>|
a$ = a$ + |<line x1="158" y1="363" x2="158" y2="369"/>|
a$ = a$ + |<line x1="366" y1="363" x2="366" y2="369"/>|
a$ = a$ + |<line x1="490" y1="363" x2="490" y2="380"/>|
a$ = a$ + |<line x1="158" y1="421" x2="158" y2="502"/>|
a$ = a$ + |<line x1="162" y1="430" x2="170" y2="430"/>|
a$ = a$ + |<line x1="366" y1="422" x2="366" y2="533"/>|
a$ = a$ + |<line x1="490" y1="434" x2="490" y2="443"/>|
a$ = a$ + |<line x1="16" y1="504" x2="162" y2="504"/>|
a$ = a$ + |<line x1="223" y1="430" x2="362" y2="429"/>|
a$ = a$ + |<line x1="235" y1="537" x2="294" y2="537"/>|
a$ = a$ + |<line x1="348" y1="537" x2="398" y2="537"/>|
a$ = a$ + |<line x1="231" y1="533" x2="229" y2="728"/>|
a$ = a$ + |<line x1="398" y1="533" x2="398" y2="572"/></g>|
' <!-- Current room -->
a$ = a$ + |<g style="fill:#ffffff; stroke:#ffffff; stroke-width:0;">|
a$ = a$ + |<polygon id="invitados" points="23,21 23,351 235,350 235,60 23,21"/>|
a$ = a$ + |<polygon id="dormitorio" points="23,512 23,722 221,722 221,529 358,529 358,438 167,438 167,512"/>|
a$ = a$ + |<polygon id="cocina" points="500,367 500,437 743,437 743,186 598,186 598,367"/>|
a$ = a$ + |<rect id="salon" x="253" y="62" width="326" height="288"/>|
a$ = a$ + |<rect id="servicio" x="23" y="368" width="126" height="126"/>|
a$ = a$ + |<rect id="bano" x="239" y="546" width="149" height="175"/></g>|
' <!-- temperature, humidity, pressure -->
a$ = a$ + |<g style="font-weight:bold; fill:aqua; stroke:blue; stroke-width:2; font-family:comic sans ms; font-size:1.75rem;">|
' cocina
a$ = a$ + |<text id="T0" x=640 y=290>22°</text>|
a$ = a$ + |<text id="H0" x=640 y=330>40%</text>|
a$ = a$ + |<text id="L0" x=640 y=370>222 lx</text>|
' salon
a$ = a$ + |<text id="T1" x=390 y=170>22°</text>|
a$ = a$ + |<text id="H1" x=390 y=210>40%</text>|
a$ = a$ + |<text id="L1" x=390 y=250>222 lx</text>|
' servicio
a$ = a$ + |<text id="T2" x=50 y=405>22°</text>|
a$ = a$ + |<text id="H2" x=50 y=440>40%</text>|
a$ = a$ + |<text id="L2" x=50 y=475>222 lx</text>|
' invitados
a$ = a$ + |<text id="T3" x=98 y=170>22°</text>|
a$ = a$ + |<text id="H3" x=98 y=210>40%</text>|
a$ = a$ + |<text id="L3" x=98 y=250>222 lx</text>|
' bano
a$ = a$ + |<text id="T4" x=280 y=605>22°</text>|
a$ = a$ + |<text id="H4" x=280 y=640>40%</text>|
a$ = a$ + |<text id="L4" x=280 y=675>222 lx</text>|
' dormitorio
a$ = a$ + |<text id="T5" x=80 y=590>22°</text>|
a$ = a$ + |<text id="H5" x=80 y=630>40%</text>|
a$ = a$ + |<text id="L5" x=80 y=670>222 lx</text>|
a$ = a$ + |</g></svg>|
html a$
return
Code: [Local Link Removed for Guests]
' *********************
' ** EspNow Test **
' ** V1.0 14/04/21 **
' *********************
' message structure: room,event,value
' event type: (M)otion, (T)emperature, (H)umidity, (L)ight
DIM type$(3) = "M", "T", "H", "L"
aMAC$ = "CC:50:E3:92:5E:41" ' MAC address of the receiver
' start network espnow
ok = espnow.begin
if ok = 0 then wlog "ESPNOW ON" else wlog "ESPNOW FAIL"
espnow.add_peer aMAC$
onEspNowError status
timer0 15000, sampling ' sample sensors every 15 seconds
wait
END
' ----------------------
sampling:
room$ = str$(rnd(7)) ' random room between 0 and 6
event$ = type$(rnd(4)) ' random event between 0 and 3
select case event$
case "M" : value$ = "1" ' Motion detected
case "T" : value$ = str$(rnd(31)+15) ' Temperature between 15 and 45 degrees celsius
case "H" : value$ = str$(rnd(80)+20) ' Humidity between 20% and 100%
case "L" : value$ = str$(rnd(601)) ' brightness between 0 and 600
end select
message$ = room$ + "," + event$ + "," + value$
wlog message$
espnow.write(message$, aMAC$)
return
' ----------------------
status:
wlog "TX error on "; espnow.error$
return