The blue bars represent energy produced by the solar panels. The orange
bars represent energy consumed by us. The Y axis is
kilowatt-hours (pay attention to the Y axis, because the
dashboard rescales it).
According to the numbers above, the solar panels generated 78% (1 -
117.4/538.6 = ~0.78) of our consumed energy for the month. Virginia has
net metering, so our power bill should be 21% of what it would be
otherwise.
On clear, sunny days the panels generate more energy than we consume:
Energy production and consumption on a sunny day.
And in a shocking twist that will surprise no one, on cloudy days the
solar panels don’t do very well:
Energy production and consumption on a cloudy day.
Here’s an example application which geocodes the command-line argument
and then prints the normalized address from the geocoding result of each
address to standard output:
packagemainimport("fmt""log""os""pablotron.org/census-geocoder/geocoder")funcmain(){for_,arg:=range(os.Args[1:]){// get address matches
matches,err:=geocoder.Locations(arg)iferr!=nil{log.Fatal(err)}// print matches
for_,match:=range(matches){fmt.Println(match)}}}
Last month I got a reel of Raspberry Pi Pico Ws. Several
will eventually be paired with BME280s and used to measure
temperature, humidity, and barometric pressure throughout the house.
That project will have to wait a few weeks until I can unpack my
soldering iron.
In the mean time I’ve been fiddling MicroPython. My thoughts so far
are below…
Ordering and Delivery
Ordering was a bit of a headache. The sites that I normally buy
from all had one or more of the following annoyances:
I finally checked DigiKey, and they had plenty of Pico Ws
in stock and none of the aforementioned shenanigans. I ordered a reel
of 20 Pico Ws for $6.00 apiece on October 3rd. The package
arrived on October 5th.
If you’ve flashed MicroPython, then at this point you can connect to
a REPL via USB serial (e.g. screen /dev/ttyACM0).
The Pico and Pico W have SWD pins, so you can still
flash via SWD if you want to; instructions are available in the
documentation.
MicroPython
MicroPython is fantastic. I was able to blink the onboard LED,
read the onboard temperature sensor, connect to wifi, and make web
requests less than an hour after unpacking the Pico W.
MicroPythonv1.19.1on2022-10-06;RaspberryPiPicoWwithRP2040Type"help()"formoreinformation.>>>importnetwork>>>wifi=network.WLAN()>>>wifi.active(True)# enable wifi>>>wifi.connect('ssid','password')# replace 'ssid' and 'password' with your SSID and password>>>wifi.status()# wait until wifi is connected (e.g., status = 3)3>>>importurequests>>>data=urequests.get('https://pablotron.org/').content# send http request, get response body>>>len(data)# print number of bytes received48693
One useful tip: machine.unique_id() returns a unique ID for the
device. This is useful because it allows you to flash the same image to
several Pico Ws and then use machine.unique_id() to uniquely
identify them. Example:
You can exhaust the RAM fairly easily by trying to fetch web content
which is larger than the available RAM. Not that I would make such a
silly mistake…
Background: Raspberry Pi 3B in a proper case with a
BME280 soldered to it to the I²C pins. The Pi 3B
is the bedroom HTPC (running Kodi) and temperature monitor.
The permit was approved on September 21st and our meter is in the net
metering queue:
From: ...@dominionenergy.com
Sent: Friday, September 30, 2022 10:34 AM
Subject: RE: Interconnection Certificate of Completion for Paul Duncan
Reprogramed: A meter exchange schedule is being set for the week of 10/3
for this project. This exchange will be an over-the-air programmed
conversion and not physical. If there are no issues with the
exchange, we will forward a PTO letter in the next 1 to 2 days.
Please let us know if you have any questions.
Kindest Regards
Net Metering
600 East Canal Street, 11^th Flr.
Richmond, VA 23219
Email: ...@dominionenergy.com
Enphase provides an optional, publicly-visible URL with solar array
details and energy production. I set up a redirect here:
Created a web-based benchmarking tool which uses web workers and
the Performance API to test with a variety of string sizes and
generates a downloadable CSV of results.
Created a set of scripts to aggregate and plot the results as
SVGs.
consth2=(()=>{// characters to match
constM=/([&<>'"])/g;// map of char to entity
constE={'&':'&','<':'<','>':'>',"'":''','"':'"',};// build and return escape function
return(v)=>v.replace(M,(_,c)=>E[c]);})();
The capture is definitely at fault, because the call times for identical
non-capturing implementations (example: h4) are comparable to
everything else.
Medium Functions
Except for the capturing regular expression implementations in the
previous section, the remaining implementations' call times were comparable
with one another. This includes:
Reducing an array of string literals and calling replace().
Several variants of reducing an array of non-capturing regular
expression with replace().
Example: h4
consth4=(()=>{// characters to match
constM=/[&<>'"]/g;// map of char to entity
constE={'&':'&','<':'<','>':'>',"'":''','"':'"',};// build and return escape function
return(v)=>v.replace(M,(c)=>E[c]);})();
Fast Functions
Three implementations are slightly faster than the others. They all use
replaceAll() and match on string literals. Their call times are
indistinguishable from one another:
Even though the call times for h7, h8, and h9 are
indistinguishable, I actually prefer h9 because:
The most legible. It is the easiest implementation to read for
beginning developers and developers who are uncomfortable with
functional programming.
The simplist parse (probably).
Slightly easier for browsers to optimize (probably).
Here it is:
// html escape (replaceall explicit)
consth9=(v)=>{returnv.replaceAll('&','&').replaceAll('<','<').replaceAll('>','>').replaceAll("'",''').replaceAll('"','"');};
Notes
The benchmarking interface, aggregation and plotting scripts, and
additional information are available in the companion GitHub
repository.
I also wrote a DOM/textContent implementation, but I couldn’t
compare it with the other implementations because web workers
don’t have DOM access. I would be surprised if it was as fast as
the fast functions above.
Object.freeze() doesn’t appear to help, at least not in
Chrome.