Expand raspi-oled post

This commit is contained in:
FliegendeWurst 2023-11-11 19:23:56 +01:00
parent 9dca5ea21c
commit 195317fe50
3 changed files with 516 additions and 6 deletions

View File

@ -1,7 +1,7 @@
+++ +++
title = "Raspberry Pi 0 W + sensors + OLED display = temperature monitoring and calendar" title = "Raspberry Pi 0 W + sensors + OLED display = temperature monitoring and calendar"
date = 2022-10-05 date = 2022-10-05
updated = 2023-10-02 updated = 2023-11-11
+++ +++
<img id="hero-img" alt="OLED display showing temperature and upcoming appointments, connected to a Raspberry Pi" src="/assets/raspberry-pi-temperature-monitoring.jpg"> <img id="hero-img" alt="OLED display showing temperature and upcoming appointments, connected to a Raspberry Pi" src="/assets/raspberry-pi-temperature-monitoring.jpg">
@ -22,10 +22,10 @@ When activating another display mode (not active in the picture), this area of t
<li>yellow push switch: TRU Components PBS-18B 701912</li> <li>yellow push switch: TRU Components PBS-18B 701912</li>
</ul> </ul>
The components are connected to the Pi as indicated in the wiring diagram below. The components are connected to the Pi as indicated in the wiring diagram below (made using [Circuit Diagram](https://www.circuit-diagram.org/)).
<embed <embed
style="background: white;" class="white-svg"
type="image/svg+xml" type="image/svg+xml"
src="/assets/circuit.svg" src="/assets/circuit.svg"
title="Wiring diagram"> title="Wiring diagram">
@ -50,7 +50,7 @@ Wiring of the AM2302 to the RPi:
Wiring of the push switch to the Pi: one pin to GPIO 19, the other to 3.3V. Wiring of the push switch to the Pi: one pin to GPIO 19, the other to 3.3V.
<h3>Software</h3> ### Software
The Raspberry Pi 0 W is running <a href="https://www.raspberrypi.com/software/">Raspberry Pi OS</a> 11 (bullseye). The Raspberry Pi 0 W is running <a href="https://www.raspberrypi.com/software/">Raspberry Pi OS</a> 11 (bullseye).
@ -74,7 +74,7 @@ It is run by another Python script (<a href="https://gist.github.com/FliegendeWu
Below is the crontab of the pi user. status_check is run every five minutes. take_measurement is run every ten minutes. Fifteen minutes into the hour, any new calendar entries are synced using refresh_json. To avoid OLED burn-in, the display is turned off every minute (if it was on previously). Below is the crontab of the pi user. status_check is run every five minutes. take_measurement is run every ten minutes. Fifteen minutes into the hour, any new calendar entries are synced using refresh_json. To avoid OLED burn-in, the display is turned off every minute (if it was on previously).
```cron ```
*/5 * * * * /home/pi/status_check /home/pi/sensors.db 2>/dev/null >/dev/null */5 * * * * /home/pi/status_check /home/pi/sensors.db 2>/dev/null >/dev/null
*/10 * * * * /home/pi/take_measurement /home/pi/sensors.db */10 * * * * /home/pi/take_measurement /home/pi/sensors.db
15 * * * * /home/pi/refresh_json --no-weekly 15 * * * * /home/pi/refresh_json --no-weekly
@ -91,7 +91,7 @@ The binaries (and the libraries they depend on) may be copied to the Pi like thi
``` ```
mkdir /tmp/nixstore mkdir /tmp/nixstore
nix copy --extra-experimental-features nix-command --extra-experimental-features flakes --no-check-sigs --to /tmp/nixstore $(readlink -f result) nix copy --extra-experimental-features nix-command flakes --no-check-sigs --to /tmp/nixstore $(readlink -f result)
rsync -r --links --info=progress /tmp/nixstore/nix pi@himbeere-null:~/ rsync -r --links --info=progress /tmp/nixstore/nix pi@himbeere-null:~/
``` ```
@ -102,4 +102,40 @@ patchelf --set-interpreter /lib/ld-musl-armhf.so.1 nix/store/*-raspi-oled-*/bin/
sudo mv nix / sudo mv nix /
``` ```
### Enclosure
<img class="content-img-tall" alt="3D model of the case" src="/assets/raspberry-pi-case.png">
To make the whole setup look a bit nicer, I designed a casing using [OpenSCAD](https://openscad.org/).
The image on the right shows the final result as rendered by OpenSCAD ([.scad](/assets/RPi-Zero.scad)).
[Raspberry Pi 0 W - Slim Case](https://www.thingiverse.com/thing:4199739) (by OhSnap) proved to be a great base to build on.
I added some supports around it to ensure it won't topple over as easily.
Since I was too lazy to measure the dimensions of my OLED display, I extracted the relevant part of [Zoid, the Trapezoidal Under Cabinet 1.5" OLED Display](https://www.thingiverse.com/thing:3397089) (by rhattie).
Feeling a little bit fancy, I decided to add some inset icons underneath.
The pin holes will be useful to add some status LEDs later.
Because one button will soon not be enough control, I added three button holders on the top.
A library near me offers a 3D printing service so it was easy to get the case printed.
The new buttons and LEDs will need to be wired up to some unused GPIO pins.
All LEDs are connected using a single resistor since these will only turn on rarely and even more rarely at the same time.
<embed
class="white-svg"
type="image/svg+xml"
src="/assets/circuit_new.svg"
title="Wiring diagram">
To make full use of the three buttons, I came up with a simple one/two-step selection menu to get to the most important functionality.
1. Show time table and large clock
1. (unused)
2. Show temperature chart
3. Show upcoming events
2. Dismiss active action
3. Show TOTP codes
1. Next page
2. (unused)
3. Show RPi screensaver
This post will be updated soon™ to show to the final 3D print (which required some adjustments not yet mentioned).

227
static/assets/RPi-Zero.scad Normal file
View File

@ -0,0 +1,227 @@
final = !$preview;
module pizero() {
difference() {
color("green") import("pizero-scase_new.stl");
if (final) {
translate([34.4, -25, 1.05]) cube([1,50,.5]);
translate([34.5, -25, 1.15]) cube([1,50,.5]);
translate([34.6, -25, 1.25]) cube([1,50,.5]);
translate([34.7, -25, 1.35]) cube([1,50,.5]);
translate([34.8, -25, 1.45]) cube([1,50,.5]);
// keep 4.75 - 5.45 = 0.7
h = 10.5;
translate([34.8, -25, 5.45]) cube([1,50,h]);
translate([34.7, -25, 5.55]) cube([1,50,h]);
translate([34.6, -25, 5.65]) cube([1,50,h]);
translate([34.5, -25, 5.75]) cube([1,50,h]);
translate([34.4, -25, 5.85]) cube([1,50,h]);
}
}
}
module oled_hole() {
intersection () {
translate([0,0,0]) import("OLED_Under_Cabinet.stl");
cube([48, 10, 40], center=true);
}
}
module led_hole() {
translate([-1.25, 19, 30]) {
rotate([90, 0, 0]) cylinder(10, .5, .5, center = true, $fn=32);
}
translate([1.25, 19, 30]) {
rotate([90, 0, 0]) cylinder(10, .5, .5, center = true, $fn=32);
}
}
module extender() {
difference() {
s = 90 - 8.5;
//s = 12.5;
h = s;
union() {
/*
translate([0, 19, 60]) {
color("red") rotate([90, 0, 0]) cylinder(10, 1, center = true);
}
*/
translate([0,0,8.5 + s/2]) linear_extrude(s, center=true) projection(cut = true) translate([0,0,-8]) pizero();
translate([33, -15, 8.5]) cube([1,30,s]);
for ( i = [ 1 : 6 ] ) {
w = 19.95;
color("red")
translate([33 + i/10, -w/2 + 0.65, 8.5 - i/10]) cube([0.7 - i/10,w,s]);
}
difference() {
union() {
translate([0,0,8]) cube([34*2,33,2], center=true);
translate([0,0,9]) cube([34*2,33,1], center=true);
}
union () {
scale([0.99, 0.99, 1]) pizero();
translate([-33,17.5,8.5]) cube([3.4,3.4,10], center=true);
translate([-34.9,16,8.5]) cube([3.4,3.4,10], center=true);
translate([33,17.5,8.5]) cube([3.4,3.4,10], center=true);
translate([34.9,16,8.5]) cube([3.4,3.4,10], center=true);
mirror([0,1,0]) {
translate([-33,17.5,8.5]) cube([3.4,3.4,10], center=true);
translate([-34.9,16,8.5]) cube([3.4,3.4,10], center=true);
translate([33,17.5,8.5]) cube([3.4,3.4,10], center=true);
translate([34.9,16,8.5]) cube([3.4,3.4,10], center=true);
}
translate([0,0,8.5]) cube([32*2,14.5*2,10],center=true);
translate([34,0,8.5]) cube([5,14.5*2,10],center=true);
}
}
}
translate([34.4, -25, 8.5]) cube([1,50,h]);
translate([0, 19, 60]) difference() {
cube([48,10,40], center=true);
oled_hole();
}
led_hole();
translate([-10,0,0]) {
led_hole();
}
translate([-20,0,0]) {
led_hole();
}
translate([10,0,0]) {
led_hole();
}
translate([20,0,0]) {
led_hole();
}
// cable hole
translate([35,0,70]) {
minkowski()
{
color("red") cube([5,5,2], center=true);
rotate([0,90,0]) cylinder(r1=2,r2=2,h=1, center=true, $fn=32);
}
}
// icons
translate([0, 17.9 - .5, 41]) {
scale = 0.19;
translate([-14, 0, 0]) scale([scale, 1, scale]) rotate([90,0,0]) linear_extrude(1) import("./rpi_logo.svg", center=true);
translate([-5, 0, 0]) scale([scale, 1, scale]) rotate([90,0,0]) linear_extrude(1) import("./Calendar_font_awesome.svg", center=true);
translate([5, 0, 0]) scale([scale, 1, scale]) rotate([90,0,0]) linear_extrude(1) import("./to cry.svg", center=true);
translate([14, 0, 0]) scale([scale, 1, scale]) mirror([1,0,0]) rotate([90,0,0]) linear_extrude(1) import("./temp.svg", center=true);
}
}
}
module button_hole() {
difference() {
cube([12.4 + 0.05, 12.4 + 0.05,5], center=true);
translate([6.05 + 0.05 / 2, -3.81, 0]) cube([0.3,2.6,5], center=true);
translate([6.05 + 0.05 / 2, 3.81, 0]) cube([0.3,2.6,5], center=true);
translate([-6.05 - 0.05 / 2, -3.81, 0]) cube([0.3,2.6,5], center=true);
translate([-6.05 - 0.05 / 2, 3.81, 0]) cube([0.3,2.6,5], center=true);
}
}
module hat() {
difference() {
translate([0,0,98.5]) mirror([0,0,1]) difference() {
union() {
pizero();
color("red") translate([33, -13.5, 2.65]) cube([1.4,27,5.85]);
color("red") translate([-33-1.4, -13.5, 2.65]) cube([1.4,27,5.85]);
color("red") translate([-30, -18.3+1.4, 2.4]) cube([60,1.4,5.85]);
translate([-30, -15, 0]) cube([60,30,1.4]);
translate([0,0,8.5]) difference() {
cube([66,32,4],center=true);
cube([63,28,4],center=true);
}
}
translate([34.4, -25, 1.05]) cube([1,50,5]);
translate([0, 0, 0]) button_hole();
translate([-20, 0, 0]) button_hole();
translate([20, 0, 0]) button_hole();
}
scale([0.99, 0.99, 1]) extender();
}
}
module sticks1(s=1) {
for ( i = [0 : 8] ){
if (i != 6) {
translate([33.7,0,20+i*8]) cube([s*.75,8,s*.75], center=true);
}
translate([-33.7,0,20+i*8]) cube([s*.75,8,s*.75], center=true);
}
}
module sticks2(s=1) {
translate([0,0,4]) sticks1(s);
}
module print1() {
difference() {
intersection() {
extender();
translate([0,50,0]) cube([1000,100,1000], center=true);
}
sticks2(1.05);
}
sticks1();
}
module print2() {
difference() {
intersection() {
extender();
mirror([0,1,0]) translate([0,50,0]) cube([1000,100,1000], center=true);
}
sticks1(1.05);
}
sticks2();
}
module print3() {
hat();
}
module pyramid() {
difference() {
union() {
for ( i = [0 : 8]) {
s = (8 - i) / 2;
translate([- s, - s, i * 0.5])
cube([4+s,4+s,.5]);
x = 2.5;
}
}
x = 2.6;
translate([4-x,4-x,1])
cube([x,x,4]);
}
}
module fixer() {
translate([0, 30, 1]) linear_extrude(2, center=true) circle(5, $fn=32);
translate([-15, 25, 1]) rotate([0,0,20])scale([1,0.1,1]) linear_extrude(2, center=true) circle(20, $fn=32);
mirror([1,0,0]) translate([-15, 25, 1]) rotate([0,0,20])scale([1,0.1,1]) linear_extrude(2, center=true) circle(20, $fn=32);
translate([0, 50, 1]) linear_extrude(2, center=true) circle(5, $fn=32);
translate([0, 40, 1]) rotate([0,0,90])scale([.7,0.1,1]) linear_extrude(2, center=true) circle(20, $fn=32);
}
module print4() {
difference() {
union() {
pizero();
translate([-34.4 , -16.9, 0]) pyramid();
translate([-34.4 , 16.9, 0]) rotate([0, 0, 270]) pyramid();
translate([34.4 , -16.9, 0]) rotate([0,0,90]) pyramid();
translate([34.4 , 16.9, 0]) rotate([0, 0, 180]) pyramid();
fixer();
mirror([0, 1, 0]) {
fixer();
}
}
translate([21.5, -17, 4.5]) cube([14, 4, 9], center=true);
translate([21.5, -25, 4.5]) cube([14,20, 7], center=true);
}
}
//rotate([-90,0,0]) print1();
//rotate([90,0,0]) print2();
//mirror([0,0,1]) print3();
//print4();
module all() {
print1();
print2();
print3();
print4();
}
all();

File diff suppressed because one or more lines are too long