Global Earthquake Display on ILI9341 TFT using ESP8266.

Place your projects here
AndyGadget
Posts: 222
Joined: Mon Feb 15, 2021 1:44 pm
Has thanked: 120 times
Been thanked: 132 times

Global Earthquake Display on ILI9341 TFT using ESP8266.

Post by AndyGadget »

Put an ILI9341 display in a 3D printed case with an ESP8266 (or ESP32) device and this makes a great little desktop gadget.
Thingiverse has some suitable cases (needs to be landsape) for different display sizes.
.
Seismic2.jpg
.
Seismic Portal is a European site which gathers seismic events (earthquakes) from worldwide regional sites in real time and makes the data and history available via its API. My program takes data from the Seismic Portal API and displays it on a map of the world, keeping a local history of the most recent 100 events; usually about a day's worth.
The most recent event is shown by a flashing red / white dot on the map with text showing the magnitude, time and region it ocurred in.
I've given two options for time - Either the actual time of the event as UTC or the time it first appeared on the data feed as your local time (as long as your config offset is correct) which will be a few minutes delayed.

Older events are displayed as slowly fading from bright red to dull orange as they move down the 100 event history.
You will rarely see all 100 as newer events at the same location will display on top of older ones. It does give a very good show of the currently most active regions in the world. California usually has several low level quakes a day and also quite a few show up in more inland states which a bit of research told me are caused by fracking and high-pressure disposal of oil industry waste water into underground fissures.

You'll need to download the attached image W1.bmp into your Program directory for the map.

Code: [Local Link Removed for Guests]

' Quakes V1.3
'
' Fixed magnitude less than 1.5 bug
' Now displaying previous 100 events
' Colour scheme now bright yellow for new fading to dull red for older events
' Added (rough) count of how many events in past 12 hours at bottom RHS
' White dot indicating API server access now at top middle
' Tweaked magnitude dot size for better display
' Improved line splitting for long region names
'
pause 2000
TFT.INIT 16, 4, 3
'May need TFT.INIT 16, 4, 1 depending on screen orientation.
pause 2000
wlog "Rebooted at " + Time$ + " on " + Date$


' Various variable definitions.
FName$ = "/program/data.txt"
OldRef$ = ""
dim Hist(100,3)
PLat = 0 : PLon = 0 : PMag = 0
EOL$ = chr$(10)
SecCnt = 0
FreqMA = 1200

' Display bare map on screen.
TFT.BMP "/W1.bmp"

if file.exists(FName$) = 1 then
  ' Read event history from file into array.
  for FCnt = 1 to 100
    FLine$ = file.read$(FName$,FCnt)
    Hist(FCnt,0) = val(word$(FLine$,1,"|"))
    Hist(FCnt,1) = val(word$(FLine$,2,"|"))
    Hist(FCnt,2) = val(word$(FLine$,3,"|"))
  next FCnt
end if

gosub QueryServer

ONWGETASYNC MsgReceived
timer0 500, Blink
timer1 60000, QueryServer
wait

QueryServer:
' Request data from SeismicPortal API - No key needed.
' JSON is an option but chose simple delimited text string output.
' Requesting only most recent event.

' White dot in top centre of screen - Clears when data received.
TFT.CIRCLE 160, 6, 3,&HFFFF,1
print Time$
wgetasync("seismicportal.eu/fdsnws/event/1/query?limit=1&format=text",443,0,1)
return

MsgReceived:
Res$ = WGETRESULT$
'Option.WDTReset
wlog Time$
wlog Res$
TFT.CIRCLE 160, 6, 3,&H3475,1
Line$ = WORD$(RES$, 2, chr$(10))
wlog line$
Ref$ = word$(Line$,1,"|")
'wlog time$ + " " + Line$

' Only process result if it is a new event.
if (Ref$ <> OldRef$) and (val(Ref$) <> 0)  then


  OldRef$ = Ref$
  TD$ = word$(Line$,2,"|")
  EDate$ = left$(TD$,10)
  
  ' Uncomment the first line for actual event time from API as UTC or use 2nd line
  ' for your local time (assuming timezone set correctly) delayed by a few minutes.
  ' ETime$ = mid$(TD$,12,5)
  ETime$ = left$(time$,5)
  
  EMag$ = word$(Line$,11,"|")
  ELoc$ = word$(Line$,13,"|")
  Lat = val(word$(Line$,3,"|"))
  Lon = val(word$(Line$,4,"|"))
  
  ' Wilder's moving average - Does not require storing all previous values.
  ' Response is similar to EMA with twice the period.
  FreqMA = ((FreqMA * 9) + SecCnt)/10
  SecCnt = 0
  
  ' Load map to clear display, then print text info about event.
  pause 200
  TFT.BMP "/W1.bmp"
  pause 500
  TFT.TEXT.COL &HFFE0
  TFT.TEXT.SIZE 3
  TFT.TEXT.POS 8,6
  TFT.PRINT EMag$
  
  TFT.TEXT.SIZE 2
  TFT.TEXT.POS 254,6
  TFT.PRINT ETime$
  
  TFT.TEXT.POS 280,220
  ' MA value scaled up to give approx. events in last 12 hours.
  TFT.PRINT str$(cint(2 * 43200 / FreqMA))
  
  ' Break location text neatly and display on 2 lines if long.
  if len(ELoc$) <= 22 then
    TFT.TEXT.POS 4,220
    TFT.PRINT ELoc$
  else
    sp = instr(14,ELoc$," ")
    TFT.TEXT.POS 4,206
    TFT.PRINT left$(ELoc$,sp)
    TFT.TEXT.POS 4,223
    TFT.PRINT right$(ELoc$,len(ELoc$) - sp)
  endif
  
  ' Shift array.
  For Cnt = 0 to 99
    Hist(Cnt,0) = Hist(Cnt+1,0)
    Hist(Cnt,1) = Hist(Cnt+1,1)
    Hist(Cnt,2) = Hist(Cnt+1,2)
  next Cnt
  
  ' Convert longitude and latitude of event to screen co-ordinates.
  ' Size of plotted circle is proportional to quake magnitude.
  PLon = 151 + (0.889 * Lon)
  PLat = 157 - ((0.75 * Lat) + (Lat * 0.0475)^3)
  'PMag = cint(val(EMag$)-2)
  PMag = cint(val(EMag$) * 0.8)
  if PMag <= 1 then PMag = 1
  
  ' Write new event to array.
  Hist(100,0) = PLon
  Hist(100,1) = PLat
  Hist(100,2) = PMag
  
  ' Plot event history from array.
  for HCnt = 0 to 100
    RedVal = 155 + HCnt
    GrnVal = 55 + (HCnt * 2)
    BluVal = 0
    ' Colour of plotted point fades from bright yellow through orange to dull red with age.
    TFT.CIRCLE Hist(HCnt,0),Hist(HCnt,1),Hist(HCnt,2),TFT.RGB(RedVal,GrnVal,BluVal),1
  next HCnt
  
  ' Plot most recent event.
  TFT.CIRCLE PLon,Plat,PMag,&HF800,1
  
  ' Store array to file.
  x =  file.delete(FName$)
  for FCnt = 1 to 100
    FLine$ = str$(Hist(FCnt,0)) + "|" + str$(Hist(FCnt,1)) + "|" + str$(Hist(FCnt,2)) + EOL$
    file.append FName$,FLine$
  next FCnt
  
endif
return

Blink:
' Flashing red / yellow dot to mark most recent event.

Flsh = (Flsh + 1) mod 2
if Flsh = 0 then
  TFT.CIRCLE PLon,PLat,PMag,&HFFE0,1
  SecCnt = SecCnt + 1 ' Counting seconds for moving average.
else
  TFT.CIRCLE PLon,PLat,PMag,&HF800,1
endif

return
W1.bmp
You do not have the required permissions to view the files attached to this post.
Last edited by AndyGadget on Mon Sep 06, 2021 12:44 pm, edited 1 time in total.
User avatar
cicciocb
Site Admin
Posts: 1899
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 407 times
Been thanked: 1269 times
Contact:

Re: Global Earthquake Display on ILI9341 TFT. - From old forum.

Post by cicciocb »

Thanks Andy,
very nice project, I personally tried on both ESP8266 and ESP32 some time ago.
It was also a good way to fox some snags on the ESP8266 :D

I modified a little bit your post enabling the annex syntax colouring and the possibility to upload .bmp.
User avatar
Fernando Perez
Posts: 378
Joined: Mon Feb 15, 2021 10:09 pm
Location: Santander (Spain)
Has thanked: 195 times
Been thanked: 267 times

Re: Global Earthquake Display on ILI9341 TFT. - From old forum.

Post by Fernando Perez »

I still find the earthquake monitoring program admirable.
I have tried to adapt it to the "new times" in terms of Annex instructions and the TFT screen that I am playing with these days, the ILI9486 of 480x320 and 3.5 inch
I have simplified the code a lot, removing the history matrix and recording in files.
And added an exit button to return to the main screen. [Local Link Removed for Guests]
Regarding the calculation of the equivalence between latitude and coordinate "y", I had to subtract 52 from the result of convert.map. Don't ask me why, because I don't know. But if I don't, the point on the map doesn't match. And I'm not sure if it's correct because I haven't seen earthquakes far enough apart yet.
One question: The original program, which in its day worked perfectly for me on a 320x240 screen, now does not show the BMP file properly, many vertical stripes appear on the map. And of course, the TFT.INIT 16, 4, 3 statement gives an error if it is not replaced by TFT.INIT 1.

Code: [Local Link Removed for Guests]

server$ = "seismicportal.eu/fdsnws/event/1/query?limit=1&format=json"
idPrev$ = ""
on = 0 : x = 0 : y = 0 : pMag = 0

tft.init 1  ' ILI9486
tft.jpg "/map.jpg"  ' Display 480x320 bare map on screen.

gui.init 1
btn = gui.button(320, 280, 60, 30, "END", 2, 5)
gui.setEvent btn, TOUCH, home
gui.autorefresh 30,1

timer0 500, blink
timer1 60000, query
gosub query
wait

' -----------------------------
query:
  result$ = wGet$(server$, 443, 0, 1)

  id$ = json$(result$, "id")
  if id$ <> idPrev$ then
    idPrev$ = id$
    wlog result$

    loc$ = json$(result$, "flynn_region")
    if loc$ = "not found" then return

     ' Load map to clear display, then print text info about event.
    tft.jpg "/map.jpg"
    gui.redraw
    tft.text.color black
        
    ' Break location text neatly and display on 2 lines if long.
    lines = word.count(loc$)
    tft.text.align 8
    for line = 0 to lines - 1
      tft.text.draw word$(loc$, line + 1), 130, 240 + (line * 20), 3
    next line  
    
    mag$ = json$(result$, "mag")
    tft.text.draw mag$, 55, 45, 4

    tEvent$ = mid$(json$(result$, "lastupdate"), 12, 5)
    tft.text.draw tEvent$, 455, 35, 3    

    lat = val(json$(result$, "lat"))
    lon = val(json$(result$, "lon"))

    ' Convert longitude and latitude of event to screen co-ordinates.
    x = cInt(convert.map(lon, -180, 180, 0, 480))
    y = cInt(convert.map(lat, -90, 90, 0, 320)) - 52

    ' Size of plotted circle is proportional to quake magnitude. 
    pMag = cInt(val(mag$) * 0.8)
    if pMag <= 1 then pMag = 1

    ' Plot most recent event.
    tft.circle x, y, pMag, &HF800, 1

    wlog
    wlog loc$
    wlog "Lon: " + str$(lon) + " => X = " + str$(x)
    wlog "Lat: " + str$(lat) + " => Y = " + str$(y)

  end if

return

' -------------------------
blink:
  on = 1 -on
  if on = 0 then tft.circle x, y, pMag, &HFFE0, 1 else tft.circle x, y, pMag, &HF800, 1
return

' --------------------------
home:
 ret = bas.load "/menu.bas"
return  
link to JPG image https://www.myrapidq.it/public/map.jpg
User avatar
Fernando Perez
Posts: 378
Joined: Mon Feb 15, 2021 10:09 pm
Location: Santander (Spain)
Has thanked: 195 times
Been thanked: 267 times

Re: Global Earthquake Display on ILI9341 TFT. - From old forum.

Post by Fernando Perez »

With more data from earthquakes, I see that my latitude-to-point conversion calculation "y" on the graph is not working correctly.
I have also tried without success with:

Code: [Local Link Removed for Guests]

' Convert longitude and latitude of event to screen co-ordinates.
    x = cInt(convert.map(lon, -180, 180, 0, 480))
    y = cInt(convert.map(lat, -90, 90, 0, 320))
    y = (320 - y) + 52
However, the conversion for the x-axis does seem correct.
Do any of you know the subject of geographic coordinates?
You can help me?
Last edited by Fernando Perez on Sun Aug 08, 2021 2:53 pm, edited 1 time in total.
AndyGadget
Posts: 222
Joined: Mon Feb 15, 2021 1:44 pm
Has thanked: 120 times
Been thanked: 132 times

Re: Global Earthquake Display on ILI9341 TFT. - From old forum.

Post by AndyGadget »

Hi Fernando. Glad you're still enjoying the program. I'm still running mine on an ESP32 on my desk and have given a couple away to friends with an interest in geophysics.

Regarding the lines on screen when loading the bitmap. Save your data and then reformat the memory. This has worked for me and at least one other I suggested it to.

The Y axis formula I worked out by manually plotting points at 30 degree intervals on the screen and running the required Y offsets through a curve fitting calculator.

You've probably already realised the X axis is shifted too. This was so the wraparound appeared in a visually more pleasing place and so the seas around New Zealand weren't on the very edge of the map; quite an active region!

We've got guests inn the room where my device and my main computer are so I'll reply later to anything I've missed. (I hate posting on forums using a small phone screen. Just call me a dinosaur :-)
User avatar
Fernando Perez
Posts: 378
Joined: Mon Feb 15, 2021 10:09 pm
Location: Santander (Spain)
Has thanked: 195 times
Been thanked: 267 times

Re: Global Earthquake Display on ILI9341 TFT. - From old forum.

Post by Fernando Perez »

Okay, if you want me to call you a dinosaur, I'll tell you.
But what will I be, that my mobile phone is a "basic phone for seniors" and if I have a smartphone it is only for WhatsApp? :?

I appreciate the quick reply. I'll keep testing. What surprises me is that convert.map works perfectly for x and not for "y".
I am recording the earthquakes in a file for a whole day and I will see the correlation between latitude and what the cursor of the Paint program indicates to me with the map loaded.
Greetings.
AndyGadget
Posts: 222
Joined: Mon Feb 15, 2021 1:44 pm
Has thanked: 120 times
Been thanked: 132 times

Re: Global Earthquake Display on ILI9341 TFT. - From old forum.

Post by AndyGadget »

I'd forgotten about convert map, but in this case it won't work as the Y axis isn't linear. The X axis is.
That's why the formula is required to get the Y dots in the right place. I'll give you more help (if you need it) once I've got access to my hobby room again (which my wife calls the 'guest bedroom').
AndyGadget
Posts: 222
Joined: Mon Feb 15, 2021 1:44 pm
Has thanked: 120 times
Been thanked: 132 times

Re: Global Earthquake Display on ILI9341 TFT. - From old forum.

Post by AndyGadget »

I've just paid way too much for quick delivery of a 3.5" ILI9488 (480x320) display rather than waiting for the slow boat from China at a fraction of the cost.
I should be receiving it tomorrow and will adapt the program to be able to use this.

(The other reason I need it quickly is I'm entering this project in the Instructables 'Maps' contest and the closing date is in a couple of weeks. I think it makes sense to have the option of the larger screen now they're supported in Annex. It's also a chance to bring the Wonders of Annex to a wider audience.)
User avatar
Fernando Perez
Posts: 378
Joined: Mon Feb 15, 2021 10:09 pm
Location: Santander (Spain)
Has thanked: 195 times
Been thanked: 267 times

Re: Global Earthquake Display on ILI9341 TFT. - From old forum.

Post by Fernando Perez »

I hope it is an error when writing and you have bought an ILI9486, because it seems to me that the ILI9488 is not compatible with Annex. I suppose Cicciocb could clarify it.
image.png
You do not have the required permissions to view the files attached to this post.
User avatar
cicciocb
Site Admin
Posts: 1899
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 407 times
Been thanked: 1269 times
Contact:

Re: Global Earthquake Display on ILI9341 TFT. - From old forum.

Post by cicciocb »

Hi Fernando,
The latest version 1.43.5 supports the ILI9481 and the ILI9488 that work at 18 bits.
Post Reply