Just received the Wemos S2 pico board from AliExpress, and thought I'd write
a simple tutorial on how to use it with Arduino, as Wemos' Getting started guide was a bit
outdated on Arduino config and did not have an OLED example.
Quick Background
I've been planning to make a DIY hardware Bitcoin wallet just for fun. To make
it even remotely secure — once you assume attackers have your internet
connected devices pwned it pretty much varying degrees of tinfoil — it's
essential that you have an external display and a button to print out your
secret key or which address you're signing your coins to go.
My ESP8266 supply was running low (have been using ), and not sure if it has
enough memory, I looked what Wemos might have nowadays, since I've
used their nice D1 Mini in several projects, such as the ATX power
control. I was very happy to
discover they had this
Wemos S2 Pico
available at a reasonable 8 € price point from LoLin AliExpress store , having an SSD-1306 compatible
OLED display and even a button. Perfect!
Note: there are clones for Wemos products for cheaper, but I
like to show my support even if it costs a dollar or two more!
Setting up Arduino for ESP32-S2 Support
Following Wemos' Getting Started tutorial, I realized the Boards list did not
include any ESP32-S2 modules. I checked that I had the "latest" 1.0.6 version
installed. After some googling lead me to this Adafruit
page,
I realised that I needed 2.0.x version that is served from a different location
(latest ESP32 branch now lives in
Github).
After following the installation
instructions
— essentially replacing the old Espressif "Additional Boards Manager URL"
in Arduino Preferences with the new one — I updated the ESP32 package to
2.0.1 and voilà: There is now the "ESP32S2 Dev Module" available in the ESP32
Boards section. Since Wemos' instructions, the USB CDC setting had changed a
bit, this is how I set it up (changes made highlighted):
Note that the S2 Pico requires you to hold Button 0 down, press Reset button
and release the Button 0 to enter flashing mode. This will change the COM port!
Thankfully, it seems to stay in that mode so you should not be in a rush to
flash.
This post outlines the basics of creating a project that combines Go (or "golang" as googling for "go" is a pain — why didn't the guys at Google think of this?) native backend serving a web UI / GUI running on SvelteKit.
In a nutshell, this involves creating a new go project, creating a simple web server program that supports serving files from a static folder, and finally creating a SvelteKit project and configuring it to produce static content into
that folder. But let's do a short detour on why this might be useful!
Combining native executable with Web UI
Native graphical user interfaces are not easy on any platform, and after
looking at Qt, WxWidgets, Electron etc. I decided all had either major
shortcomings, huge learning curves or resulted in way too large packages.
Doing a native web server, on the other hand, is quite easy using Go. I
also investigated C and C++, but at least on Windows you very quickly run
into MinGW vs. Visual Studio issues, runtimes, build systems and all that chaos,
whereas Go pretty much produces executables with minimum fuss.
Once you have a web server, you can just serve a web UI and the user
can run the executable and open the UI in their browser.
Simple web server with Go
Once you are comfortable creating a "Hello world" level app in Go, making a
simple app for web server is not too hard:
$ mkdir project
$ cd project
project$ go mod init example/project
Here's a simple web server you can paste into main.go
package main
import (
"encoding/json"
"log"
"mime"
"net/http"
)
func databases(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*") // for CORS
w.WriteHeader(http.StatusOK)
test := []string{}
test = append(test, "Hello")
test = append(test, "World")
json.NewEncoder(w).Encode(test)
}
func main() {
// Windows may be missing this
mime.AddExtensionType(".js", "application/javascript")
http.Handle("/test", http.HandlerFunc(databases))
http.Handle("/", http.FileServer(http.Dir("static")))
log.Fatal(http.ListenAndServe(":8080", nil))
}
Today as I was finishing my Go+SvelteKit article, I ran into frustrating
Chrome error message:
Failed to load module script: Expected a JavaScript module script but the
server responded with a MIME type of "text/plain". Strict MIME type checking
is enforced for module scripts per HTML spec.
Don't you just love Chrome? It knows what it needs to do (load a JavaScript
module), but utterly refuses to do that because of a wrong MIME type. This
happened with a client-side SvelteKit application, when it tried to open some
part of the .js code.
At the time of writing, it seemed I could not find the answer easily to this
one, but there actually seems to be a StackOverflow solution discussing
this. But to help others hitting the same issue:
The problem on my Windows install was likely that Windows 10 registry did not
contain a MIME type definition for .js files. Informing user how to tweak
registry to get your program working is not ideal, but thankfully you can
augment the mime types:
import "mime"
func main() {
// Windows may be missing this
mime.AddExtensionType(".js", "application/javascript")
// And then you create the FileServer like you normally would
http.Handle("/", http.FileServer(http.Dir("static")))
}
After adding the mime fix, remember to force reload Chrome page (hold Control key down while you press refresh), otherwise the problem persists as Chrome does not
really bother reloading the offending files.
Continuing from my Project Euler Problem
1,
here are the next two Euler problems and some reflection!
Project Euler Problem 2
The second problem asks to find the sum
of even Fibonacci numbers
numbers below four million. For procedural languages, this is quite walk in the
park, but for me a concise method to produce the series in Clojure proved a bit
of a brain nugget!
Python 3
For Python, I decided to make a simple generator that yields the Fibonacci
numbers below a given treshold N. Rest is just list comprehension:
def fib(N):
i, j = 0, 1
while j < N:
yield(j)
i, j = j, i+j
print(sum(i for i in fib(4e6) if i%2==0))
C++
In C++ it's natural to just loop with a conditional addition. This
time I decided to drop using namespace std; to save a few characters.
Without i, j = j, i+j syntax, the temporary variable ij is a bit ugly.
#include <iostream>
int main() {
int i=0, j=1, s=0;
while(j<4000000) {
if(j%2==0) s += j;
int ij = i + j; i = j; j = ij;
}
std::cout << s << std::endl;
}
}
This site has been migrated from Wordpress to 11ty based static site. I took the posts, categories, tags and comments as JSON data and made the necessary templates for conversion. Everything should be alot faster now.
The look is still a bit bare, and some things like tables seem a bit broken. Will address these issues hopefully during upcoming days, weeks and months. Enjoy!
PS. Comments are currently disabled, I was only receiving spam in any case. You
can check out my homepage at https://joonaspihlajamaa.com/ if you want to
contact me.
I've long thought about learning
Lisp. Some time
ago I ran across Clojure and the map, set and
vector implementations felt like a modern addition. It's running on top of
JVM which is nice in
a sense, but a major pain in the ass when installing. Well, I swallowed my
wow to never install JDK again and got Clojure running quite painlessly.
To learn the ropes, I thought it would be a fun idea to rewrite Project
Euler problems 1-10 with Clojure to see how
it would compare against my language of choice for these types of algorithmic
problems, Python.
Just to make it more fun, I decided to implement them in my second favorite
language, Javascript as well. Since ECMAScript
9,
it's actually a pretty powerful and concise language, and coupling it with
Node.js unleashes some serious usage options outside
just web pages. Npm dependency hell sucks, but that's a topic for another post.
For more bare metal, I'm also doing C++ (basically sticking to C functionality
until maps and sets make themselves useful). Let's see how the languages stack up!
Project Euler Problem 1
The first problem in Project Euler is simple, add up numbers below 1000 that
are divisible with either 3 or 5 (or both). Modulo operator % can be used
to get the remainder of a number when divided by 3 and 5, and basically we
add all numbers that have either modulo as zero.
Python 3
With Python, the most concise implementation is to use the sum(iterable) and
a list comprehension, netting us a nice one-liner:
print(sum(i for i in range(1000) if i%3==0 or i%5==0))